tags:

views:

271

answers:

4

I have this class :

package scripts;

public class TestStatic {
 public static void main(String[] args) {
  new IncrA().incrStatic();
 }
}

class Static {
    public static int CPT = 0;
}

class IncrA{
 public void incrStatic(){
  for (int i:Range.ints(0,100)){
   System.out.println("Now with "+this.toString()+" : Static.CPT="+Static.CPT);
   Static.CPT++;
   try{
    Thread.sleep(100);
   }
   catch(Exception e){
    e.printStackTrace();
   }
  }
  System.out.println("Finally for execution of "+this.toString()+" : Static.CPT="+Static.CPT);
 }
}

Now I run the class TestStatic in java from the command line, twice.

javaw -cp ... scripts.TestStatic > 1.txt
javaw -cp ... scripts.TestStatic > 2.txt

I was expecting that the first and second executions would interfere, and get a value for Static.CPT == 200 in the end, because I thought the JVM would load only once the Static class. It seems it is not the case. Although I like it, I wonder if this example of mine is enough to conclude that the JVM completely separates exectutions. Actually, when I read my output, the hashCode for my IncrA object is often the same in both executions :

From 1.txt :

...
Now with scripts.IncrA@19f953d : Static.CPT=72
Now with scripts.IncrA@19f953d : Static.CPT=73
Now with scripts.IncrA@19f953d : Static.CPT=74
Now with scripts.IncrA@19f953d : Static.CPT=75
...

From 2.txt :

...
Now with scripts.IncrA@19f953d : Static.CPT=72
Now with scripts.IncrA@19f953d : Static.CPT=73
Now with scripts.IncrA@19f953d : Static.CPT=74
Now with scripts.IncrA@19f953d : Static.CPT=75
...

The @19f953d is shared among the two executions.

I googled for deep explanations on static keyword but did not find anything about these issues. Could someone explain or give a nice pointer ?

+4  A: 

The short answer: static variables only persist within a single JVM run, so after your first execution exits the fact that CPT was set to 100 is effectively lost. See http://java.sun.com/docs/books/tutorial/java/javaOO/classvars.html for a primer on static vs. non-static variables. Succintly, the only difference is that static variables are shared by all instances of a class - otherwise, they basically behave identically.

The long(er) answer is that static variables are kind of like instance variables but for the Class object for your class. When the JVM exits, all the classes are unloaded and so the static variables no longer exist just like any instances of the class no longer exist. When you restart Java for the second run, it rereads the definition of your classes from your (compiled) source files, and sets CPT to zero just as you asked it to.

(And in the situation you mentioned, running two JVMs at once leads to two ClassLoaders and two distinct Class objects, one per JVM, so they each have their own versions of the static variable.)

If you want to persist any information between Java executions, you'll need to store it somewhere external (e.g. a file or database), and load this information on startup. If you want to share information between running Java processes, you'll need to have them communicate with each other to share this information (e.g. over TCP connections). This is true regardless of whether the variables in question are static or not.

Andrzej Doyle
same time doesn't matter, you'll still have two JVMs runnings. JVMs won't share static variables
sfussenegger
Alright, thanks a lot. It's very nice to know that there is 1 instance of each Class per ClassLoader.
subtenante
Just to add to the answer above, you can have more than one Class Loader in the same JVM which can lead to two or more copies of the same class with separate static variables. It usually happens in application and web servers where different class loaders are used to separately load different applications running in the same JVM.
Gregory Mostizky
Nice to know, thanks Gregory.
subtenante
+1  A: 

static fields are only static within the scope of one JVM i.e. one execution. The creation "@19f953d" isn't defined and might or might not be equal for two consecutive executions.

sfussenegger
+1  A: 

You've launched two copies of JVM and each copy has loaded an instance of Static. By the way, static classes are unique per class loader, so it's possible to actually get two instances within the same JVM.

It's best to avoid using keywords as identifiers (Static) even if capitalised.

Totophil
A: 

Nothing persist between JVM invocations.

Static in shared by all instances of the same class, not accross JVMs.


Even if they are launched at the same time, it doesn't matter. They don't communicate, each have its own memory space.

KLE