java - Static 标识的字段或者是代码块,真的是在类加载的时候初始化的吗?
PHPz
PHPz 2017-04-18 10:52:20
0
8
704
class AAA {
    static {
        System.out.println("class AAA static block println"); // 并没有打印此句
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println("hello world!");
    }
}

一直以来都以为 static 标识的代码块或者是字段,都是在类加载的时候就被执行或者赋值了,但是这么一看....感觉自己的世界观都要被刷新了。

所以此处是类没有被加载吗?还是说我们一直以来认为的,静态代码块、字段都在类加载的时候被初始化的,这个观点是错误的?

在《深入理解Java虚拟机:JVM高级特性与最佳实践 第2版》中找到一些线索,如下图:

所以,照这么说,是在第一次主动访问该类的时候执行?小弟好生迷惑啊....大家快说说你们的观点

PHPz
PHPz

学习是最好的投资!

reply all(8)
左手右手慢动作

Class initialization and object initialization.

The code blocks and variables contained in static are only executed when the class is initialized, and you also know the five conditions for initialization.

Please provide additional explanation clearly.
First of all, even if you put them in the same .java file, after compilation, they are still two different class files. If you don’t believe me, take a look at the .class file generated under the corresponding package of bin.
Second, when a class is initialized, the static variables of the class will be initialized and the static code block will be run. Therefore, the virtual machine stipulates five initialization conditions, such as the use of new, getstatic, putstatic instructions, the class where the main function is located, reflection, parent class, etc. However, except for these five situations, the initialization of the class cannot be triggered. As shown in your code, in Main.class, there is no call or parent-child relationship or reflection about AAA.class. Therefore, AAA.class will naturally not be initialized.

You can read another blog about the loading process of java classes

Understand?

阿神

-XX:+TraceClassLoading
If you add this, you will find that AAA is not loaded

洪涛

Here are two concepts that need to be discussed:

  1. Class loading mechanism

  2. Java, compiler, bytecode, JVM specifications and implementation.

Class loading is completed through the class loader (Classloader). The specific loading strategy depends on the specific implementation of the JVM. Generally speaking, it can be divided into two types:

  1. Hungry loading, loading as long as it is referenced by other classes.

  2. Lazy loading, loading when the class is accessed.

Java, compiler, bytecode, and JVM have their own specifications, and they work together through the specifications:

Compile button compiles Java code into a standardized bytecode file. Each class (external class, internal class, anonymous class) will be compiled into a separate bytecode file (class file). When the JVM loads the class Load them one by one from these class files.

Now back to your code:

In the Java layer, you put the two classes AAA and Main in one file. After compilation, the compiler generates two class files: AAA.class and Main.class.
The two classes are together in terms of code organization, but they are independent after compilation, and Main does not reference AAA, so no matter which class loading method is used, it will not trigger the loading of class AAA, and it will not Execute static code blocks in AAA.

左手右手慢动作

Thank you very much to the enthusiastic netizens upstairs for their answers!

Verify

The AAA class is indeed not loaded, only the Main class is loaded (screenshot of the question: the fourth initialization condition, the main class is automatically loaded by jvm)

java -XX:+TraceClassLoading Main

Conclusion

The static fields|code blocks in the class are really initialized or executed when the class is loaded!

Extension

How to know whether the class has been loaded by jvm?

This is also a problem I have been struggling with. At first, I thought it was just a matter of executing the javac 命令,类就被 jvm 加载了,其实不然,该命令只是将 .java 文件转化成 jvm 能读懂的 .class file.

So how do you know whether the class has been loaded by jvm?
According to "In-depth Understanding of Java Virtual Machine: JVM Advanced Features and Best Practices 2nd Edition" and enthusiastic answers from netizens, there is no clear timing stipulating when it will be loaded!

But! jvm clearly stipulates the timing when a class is initialized-the four types in the screenshot on the question stem! Class loading takes precedence over class initialization, so here, we can temporarily think that these situations are the conditions that trigger class loading.

My brother is ignorant and summed up something wrong, please correct me! Thanks

PHPzhong

Put your Main.java and AAA.java in the same folder,

Write it in the main function

Class.forName("AAA");

Execute

大家讲道理

When the main method is executed, only the Main class will be loaded. The AAA class is not used in the Main class and the AAA class will not be loaded. It does not mean that writing the two classes AAA and Main to the same file will load them at the same time

大家讲道理

The AAA class is neither new elsewhere, nor does it correspondingly obtain or set static fields, nor invoke static methods.
So it will not be initialized automatically.

迷茫

Put it in two classes. The main one in the class declared as public starts to execute. That class is not used and will not be loaded, let alone initialized

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template