Java:不同执行中的静态字段行为

Java:不同执行中的静态字段行为,java,static,Java,Static,我有这门课: 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:

我有这门课:

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);
    }
}
现在,我从命令行两次运行java中的TestStatic类

javaw -cp ... scripts.TestStatic > 1.txt
javaw -cp ... scripts.TestStatic > 2.txt
我希望第一次和第二次执行会产生干扰,并最终得到Static.CPT==200的值,因为我认为JVM只会加载静态类一次。看来情况并非如此。虽然我喜欢它,但我想知道我的这个例子是否足以得出JVM完全分离执行的结论。实际上,当我读取输出时,IncrA对象的哈希代码在两次执行中通常是相同的:

从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
...
从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
...
@19f953d
在两次执行中共享


我在谷歌上搜索了关于静态关键字的深入解释,但没有找到任何关于这些问题的信息。有人能解释一下或者给出一个好的指针吗?

简短的回答:
静态变量只在一次JVM运行中存在,因此在第一次执行退出后,
CPT
被设置为100的事实实际上就丢失了。有关静态变量与非静态变量的入门信息,请参阅。简而言之,唯一的区别是静态变量由类的所有实例共享——否则,它们的行为基本相同

长期(呃)答案是,静态变量有点像实例变量,但对于类的
对象而言。当JVM退出时,所有类都被卸载,因此静态变量不再存在,就像类的任何实例不再存在一样。当您重新启动Java进行第二次运行时,它会从(编译的)源文件中重新读取类的定义,并按照您的要求将
CPT
设置为零

(在您提到的情况下,同时运行两个JVM会导致两个
classloader
和两个不同的
Class
对象,每个JVM一个,因此它们都有自己的静态变量版本。)


如果您想在Java执行之间持久保存任何信息,您需要将其存储在外部某处(例如,文件或数据库),并在启动时加载这些信息。如果希望在运行的Java进程之间共享信息,则需要让它们相互通信以共享此信息(例如,通过TCP连接)。无论所讨论的变量是否是静态的,这都是正确的。

静态字段仅在一个JVM(即一次执行)的范围内是静态的。创建“@19f953d”未定义,两次连续执行可能相等,也可能不相等。

您已启动了两个JVM副本,每个副本都加载了一个静态实例。顺便说一下,每个类加载器的静态类都是唯一的,因此实际上可以在同一个JVM中获得两个实例


最好避免使用关键字作为标识符(静态),即使是大写的。

JVM调用之间没有任何持久性

静态由同一类的所有实例共享,而不是由accross JVM共享



即使它们同时发布,也没关系。它们不通信,每个都有自己的内存空间。

同样的时间不重要,您仍然有两个JVM运行。JVM不会共享静态变量,非常感谢。很高兴知道每个类加载器都有一个类的实例。再加上上面的答案,在同一个JVM中可以有多个类加载器,这可能导致同一个类的两个或多个副本具有单独的静态变量。这通常发生在应用程序和web服务器中,其中使用不同的类加载器分别加载在同一JVM中运行的不同应用程序。还有一个相关的问题和答案非常简单,即每个进程都有一个静态字段的副本,每个进程也运行类初始化器