By definition, there can be a single instance of a Java singleton class. Except of course when there's obviously several, including the same code running on different physical machines, virtual machines, Java Virtual Machines.
Is the insurance that a JVM has a single instance of a singleton class?
In what domain is a Java singleton class unique? What relation to the notion of application, whatever the meaning of that is? What relation to the notion of process or thread in the operating system hosting the JVM? Of user connection in a web server? Does it change if we are talking Apache or Tomcat?
I design a Java class to be supplied to other software developers, which will access a remote functionality through it. That functionality is implemented redundantly on several distant machines. The class keeps a list of these machines, tracks their response time, and makes sure the requests received from its callers are sent to the currently most responsive distant machine. That's a good use case for a singleton.
I have only a vague idea of what the other developers will call my class from. I know that's going to be a web server, accessed by end users. I know the other software developer's code is written in Java (because the code I replace is C and called from JNI). They talk about calling my code from several apps they make on the same machine, but I do not know what exactly that means. Definitely some run their web server on Tomcat with multiple apps in the same server. Another apparently lean towards Apache Web Server, and yet another mentioned NGINX. The less I know about what they do, the better.
I know my code will run in relatively few JVMs instances on the same machine (as shown by top), and I can live happy with that few instances of my singleton. It would be a serious issue if there was 1 singleton per end user of the web server, a mild issue is there was one per "app". I'd like to know at the design phase, rather than discover in the field.
Usually the class loader loads only a single instance of each class into memory. So all static variables exist only once per Java VM.
But in web applications (e.g. on Apache Tomcat or similar) it's a bit different because each application has its own class loader and there is another class loader for shared libraries.
When your Tomcat runs two applications which contain the same library (inside the *.war), you have effectively two instances of the same library in memory, so their static variables exist twice. But when two applications share a library from the lib folder, then you have only one instance in memory.
However, by implementing a custom class loader, you can alter that behavior and then it's up to you.
Thread do not affect this normally unless you write your own class loader with specific features for threads.
Related
GlassFish allows creating N domains. Every domain has its own Java classes (libraries etc) and system settings.
For example, we have two domains - domain1 and domain2.
Via GF web console (http://localhost:4848) one system property was set for domain1 - com.temp.foo=test1. Besides via GF web console (http://localhost:7575) one system property was set for domain2 - com.temp.foo=test2.
Now, in domain1
System.out.println(System.getProperty("org.temp.foo"))
//returns `test1`
And in domain2
System.out.println(System.getProperty("org.temp.foo"))
//returns `test2`
As I understand GF and all its domains are running in one instance of JVM. And I don't understand how it is possible in one instance of JVM separate system properties. Could anyone explain?
Note: I understand that it can be a very long explanation that's why I am asking only about main principle and solutions/libraries names in an order I could read about them on the internet.
It seems that the understanding "GF and all its domains are running in one instance of JVM" is wrong.
As per GlassFish current version's documentation (chapter 3):
A domain contains a group of GlassFish Server instances that are administered
together. [...] A GlassFish Server instance is a single Virtual Machine for the Java platform (Java
Virtual Machine or JVM machine) on a single node in which GlassFish Server is
running.
That means, every single instance of any domain is running in its own JVM! As a consequence, they all could have their own different system properties.
To be fair: There are means for administering virtual servers in GlassFish, that seem to share a JVM, but I think you are not speaking about them.
Products such as GlassFish, JBoss, WebSphere, ... "simply" make use of the Java class loading mechanism to create isolation. By using multiple class loaders, even a static class fields could exist "more than once"; and each "domain" gets its very special version of that.
Start reading here, or there for example:
Application Universe – Each Java EE application has its own class loader universe, which loads the classes in all the modules in the application.
And beyond that, look into this.
In other words: although the System class obviously represents a "system view" - the class loading mechanism should make it possible to give different System class instances to each domain. Thereby making it possible to have domain-specific properties within each domain-specific System class. But to be precise: I could not find clear evidence to back up this statement. On that topic, here and there should help (the later one indicating that there even ways to tamper with the system classloader).
But thinking further, there is a problem with that idea: there are actually two class loading mechanisms. There "system/user" class loaders ... and the initial bootstrap classloader.
And the bootstrap classloader is actually "baked" into the JVM (it is implemented in native code for example) - and it can't be replaced.
And java.lang.System should be loaded by that bootstrap classloader!
So it is impossible to use "classloader magic" to enable "per domain" System properties!
The other option I see is to create a Java agent that intercepts calls and manipulates their result (see here as starting point).
But again; agents come "after" bootstrapping has completed!
So the only logical conclusion (taking what is left after excluding all options): the premise of the question must be wrong!
It is simply impossible that different "applications" running on the same JVM give different system properties. And luckily, the great answer by Seelenvirtuose confirms that conclusion.
I am creating a web front end using an existing back end containing several singleton classes. The DataStore is initialized by passing a user object into it, which is fine in a desktop application environment where the app is launched once on each machine, but will not work in a server side application designed to cater for multiple users.
The database guys are reluctant to change the service layer and remove these singletons to allow an instance per user, or allow a single instance of a service layer object to serve multiple users. This is with good reason, the desktop app has been in use for 10 years and changes could have serious side effects for the desktop app.
I have been asked to investigate using classloaders to create multiple instances of the singletons. I am not comfortable with this idea at all, hacking singletons seems like bad practice, but changing the service layer could take months of work.
I have tested this out already by putting two identical WAR files of my app (with different file names) into Tomcat. Tomcat creates a classloader for each webapp and they worked just fine separately. I only encountered problems when the singletons used System.setProperty/System.getProperty, which is to be expected as the System class comes from a classloader much higher up in the tree.
To get this separation within a single webapp, it starts to get a bit complicated. It seems I would have to create a different classloader for each session, and use the classloader to load either all the classes in the whole service layer or just the ones which are singletons and their dependencies.
The problem comes when I'm thinking about how to use these objects in a session in a servlet. Because each Servlet has a single instance within a Tomcat, getting objects from the session and casting them will not be straightforward. Eg, to get a DataStore object from the session, I would have to cast it to the correct DataStore class loaded by the correct ClassLoader, since a single class loaded by two different ClassLoaders counts as two completely separate classes.
I have read that using ClassLoaders can cause all sorts of problems with memory leaks if they are not used carefully, and from the sounds of this, if I have 500 users, that is a lot of classloaders and classes loaded by classloaders. Won't I then have also have issues with PermGen?
I suppose from this large explanation, I really have 4 questions:
Hacking a singleton with classloaders in a webapp. Creating potentially hundreds of instances of the same classes designed to be singletons. Is that a terrible idea? So terrible I shouldn't contemplate it?
What is the best way to implement this if I absolutely have to?
How do I cater for casting in a Servlet, if I want to get and set objects into a session?
Will I end up with issues with memory leaks, and PermGen space?
I would really appreciate any suggestions. Thanks :)
It's not ideal, but I don't think it's terrible. In practice, it's not much worse than loading multiple versions of the same class (even without singletons), and that's becoming increasingly common in complex application server environments, particularly those with OSGi.
It's hard to say which approach is best, but to begin with, I would start by creating child class loaders of your web application class loader. Arrange to load implementation classes in the child class loaders (i.e., the ones with the singleton), and it possible, have the implementation class implement an interface that is loaded from the web application class loader.
By loading the interface from the web application class loader. This is basically the same approach that the application server itself is using to invoke your HttpServlet: the interface is loaded by the server, so it can refer to it directly, but the implementation is in a child class loader for your application. You're just creating a secondary layer of interface/impl split for your own convenience.
You'll end up with memory leaks if you store references to the child class loader (or its loaded classes, or instantiated objects from those classes) in a "parent" class loader (e.g., if the singleton registers an MBean, which causes it to get referenced in a JVM-wide object), but that's no different from if you weren't creating child class loaders. If you're dynamically creating/destroying these singletons (thus child class loaders), you'll have to take care that you don't retain references to those child class loaders (or classes/objects) longer than necessary. PermGen is probably more problematic. If you can run with Java 8, that's gone away; otherwise, you might have to increase the default PermGen size depending on how many of these class loaders/singletons you need to create.
If I deploy and run 2 instances of same application on a single instance of Tomcat(Or any other server). Then a single object(of a Singleton class) would be created:
Across single instance of Tomcat (but common for 2 instances of same application) OR
Across application instance (different for 2 instances of application)
So essentially I want to understand that is it always a case that a single object of Singleton class gets created per JVM? How does this works in case of application hosted on a Web server(or container).
If you have a singleton class and you run two webapps that use this class in Tomcat both webapps will get 2 different instances of this singleton in JVM running the Tomcat.
But if your webapp will use a singleton from JRE or Tomcat shared libs, eg Runtime.getRuntime webapps will get the same instance of Runtime.
This is because Tomcat uses individual class loaders for webapps. When a webapp class loader loads a class it first tries to find it on webapp class path, if the class is not found it asks parent class loader to load the class.
A singleton is normally tied to a ClassLoader only.
So if you have a singleton based on a .class file in your .war file, and you deploy this web application multiple times, each application gets its own singleton.
On the other hand, if the .class file of your singleton is in the classpath of tomcat, then you only have one instance. This .class does not belong to a specific web application (it belongs to the tomcat instance).
If you have the singleton in both locations, it depends on the class loader hierarchy, and you can possibly select between "parent first" or "web application first".
It is possible to create such a singleton by assuring that you always query the same ClassLoader for the singleton. I wrote an extensive explanation in this other answer.
The Tomcat creates new class loader for each web application.
So if your Singleton class is stored in war file, the same war file will have two instances in Tomcat container i.e. it creates two separate Singleton class for each war file.
If the Singleton class is in Tomcat's share library path, Tomcat creates only one Singleton instance for the both application.
JVM analogy:
JVM is like big mansion. It contains combined family with serveral applicance and libraries.
ClassLoaders are family members, each family member represents one ClassLoader (works as delegate hierarchy not inheritance hierarchy). Note: ClassLoader is class, it can create multiple instances.
Applications are like appliance. for example: Washing Machine, Fridge, Air Cooler, Television, Dining table, Sofa and so on...
Libraries are each one having his own individual library. Every one search in parent's library if not found then search in his own library.
limitations:
If father buy an appliance their children can use it, but it can not used by his parent and siblings.
Each application might use different versions of the same libraries. i.e. If library contain two or more versions of same books, it picks whichever the book is available first.
Each family number can use only one unique appliance.
In home, we can use multiple appliance of same version. So, JVM allows us to run multiple applications of same versions.
Garbage Collector is a servant in Mansion, who roams as a daemon, who can clear any kind of Objects.
The scope of a static variable is limited to one per ClassLoader.
<shakey-ground>As far as I know, a singleton is unique per classloader. So I think the answer to your question depends on the way the container loads the web application.
If it allocates one classloader per web app, then it seems like you would get two, completely independent, singleton objects. If it allocates one classloader and all web apps use it, then they share the same singlet one instance.</shakey-ground>
So I have a fairly complex applet structure from a couple years back, and I have a question about a global class that is in it. Basically, I have three applets on the same page and they interact with each other in different ways. The part I'm confused about is the fact that they all share global (static) variables from the same class. How exactly is this happening? I was under the impression that each applet would have its own little environment and would thus be unable to access the same static variables as the others? For example if I have this in applet A:
Globals.globalVar = 5;
And this in applet B:
int x = Globals.globalVar;
And I ensure that B starts AFTER A then x will become 5. I would like to know how exactly this is handled in the JVM, as it doesn't quite make any sense to me. Does this behaviour imply that if you have two separate java applications running at the same time they can access each others static variables? Thanks beforehand.
Because that's how it's defined, for backward-compatibility reasons. See http://download.oracle.com/javase/6/docs/technotes/guides/jweb/applet/applet_execution.html#cache:
Normally, if two applets have the same codebase and archive
parameters, they will be loaded by the same class loader instance.
This behavior is required for backward compatibility, and is relied on
by several real-world applications. The result is that multiple
applets on the same web page may access each others' static variables
at the Java language level, effectively allowing the multiple applets
to be written as though they comprised a single application.
While this feature enables certain kinds of applications to be
conveniently written, it has certain drawbacks. It interferes with
termination of applets, in particular when multiple instances of the
same applet are active. It makes the programming model for applets
more complex, since it is under specified exactly when the static
fields of an applet will be re-initialized, and when they will be
maintained from run to run of the same applet. It causes imprecise
behavior of certain user interface operations within the Java Plug-in
due to the inability to identify exactly which applet initiated a
particular request.
For this reason, the new Java Plug-in provides a way to opt out of the
use of the classloader cache on an applet by applet basis.
I know that a servlet container, such as Apache Tomcat, runs in a single instance of the JVM, which means all of its servlets will run in the same process.
I also know that the architecture of the servlet container means each web application exists in its own context, which suggests it is isolated from other web applications.
As depicted here:
Accepting that each web application is isolated, I would expect that you could create 2 copies of an identical web application, change the names and context paths of each (as well as any other relevant configuration), and run them in parallel without one affecting the other. The answers to this question appear to support this view.
However, a colleague disagrees based on their experience of attempting just that.
They took a web application and tried to run 2 separate instances (with different names etc) in the same servlet container and experienced issues with the 2 instances conflicting (I'm unable to elaborate more as I wasn't involved in that work).
Based on this, they argue that since the web applications run in the same process space, they can't be isolated and things such as class attributes would end up being inadvertently shared. This answer appears to suggest the same thing
The two views don't seem to be compatible, so I ask you:
Do servlet containers prevent web applications deployed to the same container from conflicting with each other?
If yes, How do they do this?
If no, Why does interference occur?
and finally, Under what circumstances could separate web applications conflict and cause each other interference?, perhaps scenarios involving resources on the file system, native code, or database connections?
The short answer is that the servlet container isolates the applications by using a separate classloader for each application - classes loaded by separate classloaders (even when from the same physical class files) are distinct from each other. However, classloaders share a common parent classloader and the container may provide a number of other container-wide resources, so the applications are not completely isolated from each other.
For example, if two applications share some common code by each including the same jar in their war, then each application will load their own instance of the classes from the jar and a static variable (e.g. a singleton) of a class in one application will be distinct from the static variable of the same class in the other application.
Now, take for example, that the applications try to use java.util.Logger (and presumably don't include their own instance of the Logger classes in their war files). Each application's own classloader will not find the class in the war file, so they will defer to their parent classloader, which is probably the shared, container-wide classloader. The parent classloader will load the Logger class and both applications will then be sharing the same Logger class.
Servlets in the same container will share some resources. I think it should be possible to deploy the same web application twice in the same container provided that you give each a different name and they don't collide on a particular resource. This would theoretically be the same as deploying two different servlets which just happen to have the same implementation, which we do all the time.
Some shared resources, off the top of my head (and I'm not an expert so don't quote any of this!):
Libraries (jars) in tomcat/common/lib (Tomcat 5) or tomcat/lib (Tomcat 6).
Settings in the global server.xml, web.xml, tomcat-users.xml
OS provided things, such as stdin/stdout/stderr, network sockets, devices, files, etc.
The logging system.
Java system properties (System.getProperty(), System.setProperty())
I suspect... static variables? I'm not sure if the ClassLoader design would prevent this or not.
Memory. This is the most common problem: one servlet can deny others availability by consuming all memory.
CPU - especially with multi-threaded apps. On the HotSpot JVM, each Java thread is actually an OS-level thread, which are expensive and you don't want more than a few thousand of them.
Doubtless there are more.
Many of these things are protected by a security manager, if you're using one.
I believe the isolation is in the class loader. Even if two applications use the same class name and package, their class loader will load the one deployed with the application.