Are Java static variables shared across instances of the same web application?
class MyClass
{
private static SomeClass myStaticObject = new SomeClass();
}
If a web application uses MyClass and multiple instances of that application is run on a web server, is myStaticObject initialized multiple times?
Typically, yes. Most containers will provide separate classloaders for each web application. This will result in the class being loaded multiple times when used by several applications, and thus resulting in multiple instances of the static variable.
Stating the Java Language Specification for reference:
At run time, several reference types
with the same binary name may be
loaded simultaneously by different
class loaders. These types may or may
not represent the same type
declaration. Even if two such types do
represent the same type declaration,
they are considered distinct.
By inference, multiple instances of static variables will exist, unless the classes are loaded only once by a parent class loader, and never loaded elsewhere by any other class loader.
I don't quite see the point of having a private static variable in MyClass. If it's private you cannot access it as a class variable from outside the class you defined it in. If you just want other classes to access this variable via a getter method you should remove the static keyword.
Related
Do Java classes have an instance on machine (JVM) level if they contain only static methods and fields?
And if yes, what are the effects of static methods and fields when doing multithreading? Any rules of thumb?
Yes, for each loaded class in the JVM there is an instance of java.lang.Class. It does not matter whether they only contain static methods/fields or instance methods/fields as well.
And this does not have any extra impact on multi-threading beyond what instance fields and methods already have. That is, as long as you realise that the value of a static field is shared between all instances.
If you want to synchronize, you need to synchronize on the java.lang.Class instance for the class (or if the method is a static method inside said class, it can have the 'synchronized' modifier on the static method to have the same effect as synchronizing on the java.lang.Class instance for the class).
One extra thing to note is that a class with the same name can be loaded by more than one classloader at the same time in the JVM- hence classes in Java are not uniquely identifier by their fully-qualified name, instead they are uniquely identifier by the combination of java.lang.ClassLoader instance used to load the class, and the fully-qualified name.
Static methods and variables are at the class level in Java, not instance level.
All shared, writable state needs to be synchronized and thread safe, regardless of static or instance.
There are no such thing as "static classes" in java. There are inner static classes, but i presume that your question its not about this type of classes.
Classes are loaded once per classloader not per Virtual Machine, this is an important diference, for example applications server like tomcat have different classloaders per application deployed, this way each application is independent (not completely independent, but better than nothing).
The effects for multithreading are the effects of shared data structures in multithreading, nothing special in java. There are a lot of books in this subject like http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601 (centered in java) or http://pragprog.com/book/pb7con/seven-concurrency-models-in-seven-weeks (that explain difference concurrency models, really interesting book)
Yes, a class with static fields and methods has exactly one instance, which is accessed through a static call.
If you use static methods, the variables declared within the method are isolated and don't need to be synchronized (the same as in C#: C# : What if a static method is called from multiple threads?).
But when your classes have static variables and you access them within a static method, there is a trade off: When doing multithreading, the access to the static variables must be synchronized. That's the reason why the singleton pattern doesn't work as good as some believe: Instantiation costs, even more if it's only singlethreaded.
Rules of thumb? Static methods with no static class variables are always good. But static classes with variables can become very evil when doing multithreading. Therefore beware of static bottlenecks!
I have two Java projects: one is a library, and the other is a console application. In the library project, I have an abstract class with a few static member variables (for global access). It looks a bit like this:
public abstract class AbstractHelper
{
public static final VarType someVar = new VarType();
}
I access the static member variables from the console application in two different classes.
For some reason, 'someVar' has unique instances across the two different classes that access it. If I access 'someVar' from an instance of Class A, I get a different object than when I access 'someVar' from an instance of Class B.
However, if I move AbstractHelper from the library project into my console application project, then it has the expected behavior (single instance of static member variable(s) shared across multiple classes)
Does anyone know why this happens?
This can happen by using different classloaders. OSGI, java-ee servers and several other technologies allow easy injection of different classloaders to the JVM.
You can resolve the problem: define both your library and your console application classes on the same classpath.
When I access a singleton Java object from withing a servlet, that object is only "single" or "one instance" for the give servlet thread or single throughout the JVM on the Server OS (like Linux)?
I mean when client connects to the servlet/service, are singleton object are unique to each thread created for each client or its unique throughout the whole JVM installed in the machine?
I think the object is unique for each user, not to the whole JVM. The only persistent information is the one you put in the user session.
I'm not sure, but I think you can acomplish to have one instance of a Class in the whole Application Server using the ClassLoader class, however I don know how it's done.
UPDATE:
Taken from the Java Article "When is a Singleton not a Singleton?"
Multiple Singletons Simultaneously Loaded by Different Class Loaders
When two class loaders load a class, you actually have two copies of the class, and each one can have its own Singleton instance. That is particularly relevant in servlets running in certain servlet engines (iPlanet for example), where each servlet by default uses its own class loader. Two different servlets accessing a joint Singleton will, in fact, get two different objects.
Multiple class loaders occur more commonly than you might think. When browsers load classes from the network for use by applets, they use a separate class loader for each server address. Similarly, Jini and RMI systems may use a separate class loader for the different code bases from which they download class files. If your own system uses custom class loaders, all the same issues may arise.
If loaded by different class loaders, two classes with the same name, even the same package name, are treated as distinct -- even if, in fact, they are byte-for-byte the same class. The different class loaders represent different namespaces that distinguish classes (even though the classes' names are the same), so that the two MySingleton classes are in fact distinct. (See "Class Loaders as a Namespace Mechanism" in Resources.) Since two Singleton objects belong to two classes of the same name, it will appear at first glance that there are two Singleton objects of the same class.
I'd say it depends on how the singleton is implemented, but all requests for a given app execute in the same VM, so it should be one instance for all requests.
EDIT: This is assuming a straight-forward Singleton implementation similar to:
public class MySingleton {
private static MySingleton _instance;
// for sake of simplicity, I've left out handling of
// synchronization/multi-threading issues...
public static MySingleton getInstance() {
if (_instance == null) _instance = new MySingleton();
return _instance;
}
}
Yes it is Singleton. But the scope of the singleton depends on where the class is located.
If it is located inside application, it is singleton for that application. If the same class is present inside another application then another object is created for that application and it is singleton for that application.
If it is located outside application and within server, it is singleton for the VM.
According to this
https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html
every Web application has it's own class loader, so the singleton will be unique for one application and it can't be visible to another
When you create a Singleton instance, all request instances will share the same instance for the current class loader it uses.
Since all the Servlets run on a webserver which runs on a single JVM, there will be only a single Singelton Object for all your servlets.
If I declare a variable static and compiled this class into a executable jar. If I start this class using batch file like this:
java MyClass
java MyClass
java MyClass
Would all 3 process share the same variable?
No. The static variable is specific to the JVM instance. More than that, in fact - it's specific to the class loader which loads the class. So if you created three separate class loaders, each responsible for loading MyClass (not just delegating to some common parent) they'd each have a separate, independent static variable in MyClass.
Static resources are per class loader and therefore, your 3 processes have obviously three different class loaders and hence, would not share the variables.
It's impossible to use static variables on a session bean code. Is this restriction arbitrary or fundamented? And why?
Best regards
As stated in the FAQ on EJB restrictions, one of the restrictions for using EJBs is:
enterprise beans should not read or write nonfinal static fields
Further expanded in the discussion on static fields:
Nonfinal static class fields are disallowed in EJBs because such fields make an enterprise bean difficult or impossible to distribute. Static class fields are shared among all instances of a particular class, but only within a single Java Virtual Machine (JVM). Updating a static class field implies an intent to share the field's value among all instances of the class. But if a class is running in several JVMs simultaneously, only those instances running in the same JVM as the updating instance will have access to the new value. In other words, a nonfinal static class field will behave differently if running in a single JVM, than it will running in multiple JVMs. The EJB container reserves the option of distributing enterprise beans across multiple JVMs (running on the same server, or on any of a cluster of servers). Nonfinal static class fields are disallowed because enterprise bean instances will behave differently depending on whether or not they are distributed.
It is acceptable practice to use static class fields if those fields are marked as final. Since final fields cannot be updated, instances of the enterprise bean can be distributed by the container without concern for those fields' values becoming unsynchronized.
It is fundamental. As per this sun documenation,
Nonfinal static class fields are disallowed in EJBs because such fields make an enterprise bean difficult or impossible to distribute. Static class fields are shared among all instances of a particular class, but only within a single Java Virtual Machine (JVM). *
static means unique for a class OR for all it's objects.
Now, javabeans are supposed to have user-specific data, static fields don't make any sense for these.
One user edits a variable, ant it'll be updated for all other users too. (at free of cost :-)).
However if you want static behaviour for these (i.e. using same data for all users), you have application for that purpose.