See class loading from a topic

Source: Internet
Author: User

There is a very classic topic, if the virtual machine loading class process is not familiar with, it is easy to answer wrong, the title is as follows:

public class Singleton{public Static Singleton instance = new Singleton ();p ublic static int a;public static int b = 0;priv Ate Singleton () {a++;b++;} public static Singleton getinstance () {return instance;} public static void Main (string[] args) {Singleton s = singleton.getinstance (); SYSTEM.OUT.PRINTLN (S.A.); System.out.println (s.b);}}

Q. What is the output of the above code? The answer is 1, 0. If you can answer that you are already familiar with the process of class loading, let's analyze why there are results.

First understand a concept, the active reference, the JVM specification and only the following are the active reference, the active reference will trigger the initialization of the class.

1. When you encounter the 4 bytecode directives of new, getstatic, putstatic, Invokestatic, if the class has not been initialized, you need to trigger its initialization first.
The above four instructions are byte code directives, which can be understood as new, get static properties, set static properties, call static methods.
A. Initialization occurs when a class is new.
B. Call a static member in the class, except for the final field, as shown in the following example, final is called but no initialization class
Note that this is in addition to the final field, because the final field has stored the value in the class's constant pool at compile time, so referencing the final static member is not causing the initialization action.
C. Call a static method in a class, the class must first be initialized.

2. When you use the Java.lang.reflect package method to make a reflection call to a class, if the class has not been initialized, you need to trigger its initialization first.

3. When initializing a class, it is necessary to trigger the initialization of its parent class if it finds that its parent has not yet been initialized.

4. When the virtual machine starts, the user needs to specify a main class to execute, and the virtual opportunity initializes the main class first.

In addition to the active references in the above four cases, it is also important to note that there are three passive references that do not trigger the initialization of the class

1. Referencing a static field of a parent class through a subclass does not cause the subclass to be initialized
2. The class reference class is defined by an array and does not trigger initialization of this class
3. Constants are stored in the constant pool of the calling class at compile time and are not inherently referenced directly to classes that define constants, so initialization of classes that define constants is not triggered

So singleton initializes the class when the JVM finds the main method entry.

The initialization of a class consists of the following steps:

1. Load of class, loaded by ClassLoader binary file into memory.

2. Connection phase, wherein the stage is divided into three processes

A. Verify that the legitimacy of the loaded bytecode is validated.

B. Prepare to allocate memory for the static variables of the class and initialize them to the default values (int is 0,double to 0.0 and so on, not the value in the code = later, note that the instance of the class is not yet generated and therefore does not involve an instance variable)

C. Parsing, resolving symbolic references to direct references.

3. Initialize, initialize the static variables of the class to the values in the program.

For Singleton, in the second step of the connection phase, instance will be assigned a value of Null,a and B will be assigned a value of 0. Then the third step is initialized, at the time of initializing the instance is the new Singleton, the constructor will be executed, when a changes to 1,b to 1, and then to initialize a, because there is no assignment action, so a is still 1, but at the time of initialization B, B will be re-assigned a value of 0, So at the time of printing, B output is 0.

Because initialization of static is performed in the order defined, if public static Singleton instance = new Singleton (), and the final initialization, the printed a and B are all 1.


In order to better understand the above process, through the JAVAP command to the class file virtual instruction output, the command is as follows Javap-verbose-private Singleton > Singleton.txt, try Javac compile Singleton before executing this command. The contents are as follows:

Compiled from "Singleton.java" public class Singleton extends Java.lang.Object sourcefile: "Singleton.java" minor version : 0 Major version:50 Constant pool:const #1 = method#10. #27;//Java/lang/object. "   <init> ":() vconst #2 = field#8. #28;//Singleton.a:iconst #3 = field#8. #29;//Singleton.b:iconst #4 = field#8. #30;// Singleton.instance:lsingleton;const #5 = method#8 #31;//Singleton.getinstance: () lsingleton;const #6 = Field#32. #33; /Java/lang/system.out:ljava/io/printstream;const #7 = method#34. #35;//JAVA/IO/PRINTSTREAM.PRINTLN: (I) Vconst #8 = class#36;//singletonconst #9 = method#8. #27;//Singleton. " <init> ":() vconst #10 = class#37;//java/lang/objectconst #11 = ascizinstance;const #12 = Ascizlsingleton;; Const #13 = asciza;const #14 = ascizi;const #15 = ascizb;const #16 = Asciz<init>;const #17 = Asciz () v;const #18 = as Cizcode;const #19 = Ascizlinenumbertable;const #20 = Ascizgetinstance;const #21 = Asciz () Lsingleton;; Const #22 = Ascizmain;const #23 = ASCIz ([ljava/lang/string;) v;const #24 = Asciz<clinit>;const #25 = ascizsourcefile;const #26 = Ascizsingleton.java; Const #27 = nameandtype#16: #17;//"<init>":() vconst #28 = nameandtype#13: #14;//A:iconst #29 = nameandtype#15: #14; B:iconst #30 = nameandtype#11: #12;//Instance:lsingleton;const #31 = nameandtype#20: #21;//getinstance: () Lsingleton; Const #32 = class#38;//Java/lang/systemconst #33 = nameandtype#39: #40;//Out:ljava/io/printstream;const #34 = class#41; Java/io/printstreamconst #35 = nameandtype#42: #43;//println: (I) Vconst #36 = Ascizsingleton;const #37 = Ascizjava/lan G/object;const #38 = Ascizjava/lang/system;const #39 = ascizout;const #40 = Ascizljava/io/printstream;; Const #41 = ascizjava/io/printstream;const #42 = Ascizprintln;const #43 = Asciz (I) V;  {public static Singleton instance;public static int a;public static int b;private Singleton (); code:stack=2, Locals=1, args_size=1 0:aload_0 1:invokespecial#1; Method java/lang/object. " <init> ":() V 4:getstatic#2;   Field A:I 7:iconst_1 8:iadd 9:putstatic#2;   Field A:I 12:getstatic#3;   Field b:i 15:iconst_1 16:iadd 17:putstatic#3;   Field b:i  20:return linenumbertable:line 10:0 line 11:4 line 12:12 line 13:20public static Singleton getinstance (); Code:stack=1, locals=0, args_size=0 0:getstatic#4;   Field Instance:lsingleton;  3:areturn linenumbertable:line 16:0public static void Main (java.lang.string[]); code:stack=2, locals=2, args_size=1 0:invokestatic#5;   Method getinstance: () Lsingleton; 3:astore_1 4:getstatic#6;   Field Java/lang/system.out:ljava/io/printstream; 7:aload_1 8:pop 9:getstatic#2;   Field A:I 12:invokevirtual#7; Method java/io/printstream.println: (I) V 15:getstatic#6;   Field Java/lang/system.out:ljava/io/printstream; 18:aload_1 19:pop 20:getstatic#3;   Field b:i 23:invokevirtual#7; Method java/io/printstream.println: (I) V 26:return linenumbertable:line 21:0 line 22:4 lIne 23:15 line 24:26static {}; code:stack=2, locals=0, args_size=0 0:new#8; Class Singleton 3:dup 4:invokespecial#9; Method "<init>":() V 7:putstatic#4;   Field Instance:lsingleton; 10:iconst_0 11:putstatic#3;   Field b:i 14:return linenumbertable:line 4:0 Line 7:10}

Note the bottom static{} static block, where all the static properties are initialized in the block, and the initialization corresponds to the third step.

First, new executes, generates an instance of singleton in the heap, and pushes a pointer to that instance into the operand stack (one of the constituent elements of the stack frame, and one to know about a set of local variables, starting with a 0-based index).

The DUP command copies the value of the top of the operand stack, noting that at this point the operand stack has two values and both are referenced by this

The next invokespecial calls the construction method through the this reference on the top of the stack, consuming the this reference at the top of the stack.

Go to the constructor, note that there is a row stack=2, Locals=1, args_size=1 all methods have a row of similar data, where stack=2 represents the length of the operand stack is 2 slots, one slot occupies four bytes, locals= 1 indicates that the local variable table length is 1, because this pointer is used here, the default method's local variable first value is the This reference, Args_size=1 here represents the parameters of the incoming method, all instance methods will be at least 1, because the default is passed the this pointer, So the constructor here will receive the This parameter by default.

Aload_0 means to stack the value of index 0 in the local variable array, where this is stacked, and then invokespecial calls the initialization method of object, Getstatic method gets the value of a and presses the stack, where a is 0, and then iconst_1 1 presses the stack, At this time there are two values in the stack, 0 and 1,iadd pop up the top of the two values and then add and press the result stack. Putstatic assigns the result 1 to a, followed by a similar operation to assign the result 1 to B. The initialization method returns, continuing the execution of the previous stack frame as a static{} block.

Putstatic assigns this reference to the instance variable, when the operand stack is empty

Iconst_0, put 0 into the stack

Putstatic assigns 0 to variable B, at which point B changes back to 0, so the final result of B is 0.

The key to figuring out the whole problem is mastering the JVM's initialization process for class variables. The first is to allocate memory for the class variable and initialize it to the default value, which is a phase, and then the initialization of the code itself in the constructor does not represent the final value, because the JVM also initializes the class variable, which is the b=0 of the Equals action, which is compiled into the static{} block. The order of initialization in a static block is related to the order in which the code is declared, that is, the order in which the constructor is called affects the final value, and the condition that the constructor is triggered is the execution of the new action. So the final output is related to the order of public static Singleton instance = new Singleton ();

See class loading from a topic

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.