Current location - Quotes Website - Signature design - Initialization of java program
Initialization of java program

As for Java initialization, there are many articles that use a lot of space to introduce it. The classic <> even uses a dedicated

chapter to introduce Java initialization. But after a large number of code examples, it still feels like it has not really penetrated into the essence of initialization.

This article uses the author's understanding of JVM and his own experience to give a more in-depth explanation of Java initialization. Due to the author's level restrictions,

as well as changes in various JDK implementation versions , there may still be many errors and shortcomings. Experts and experts are welcome to give advice.

To understand Java initialization in depth, we cannot know the order in which the JVM is executed from the program flow. Understanding the JVM execution mechanism and stack traces are effective means. Sadly, so far. JDK1.4 and JDK1.5 still have bugs in the javap function.

Bugs exist. So for some processes I cannot prove to you two opposite situations with actual results (but I can prove that it is indeed a BUG)

<>(Third Edition) At the beginning of Chapter 4 , describes the initialization work of Java in this way:

The following translation is original:

It can be thought that each class has a method named Initialize(), and this name implies It must be called before use. Unfortunately, if you do this, the user will have to remember to call this method. The designers of the Java class library can pass a method called a constructor < /p>

Special method to ensure that each object can be initialized. If the class has a constructor, then Java will just create the object before the user can get it

, automatically call that constructor, so that initialization is guaranteed.

I don’t know how big the difference is between the original author’s description and the translator’s understanding. Combining the whole chapter, I didn’t find the two most critical words ""

and" ". At least it means that the original author and translator did not really explain what the JVM did during initialization, or they did not understand the inside story of JVM initialization

Otherwise, why should we think that there are these two methods? What about an "Initialize()" method that doesn't actually exist?

Where are the "" and "" methods?

These two methods are methods that actually exist but you cannot find. Perhaps it is this that makes some masters dizzy. Coupled with some bugs in jdk implementation, it is really confusing if you don't have a deep understanding.

There is a strange phenomenon in the current scientific system. Such a huge system is initially based on a hypothesis. Hypothesis 1 is correct.

From this, 2 is deduced. Then continue to derive 10000000000. It's a pity that too many people don't care at all. Systems like 2-100000000000 are based on the assumption that 1 is correct.

I won't use the assumption "you can think so", I want to prove that the ""

and "" methods really exist:

packagedebug;

p>

publicclassMyTest{

staticinti=100/0;

publicstaticvoidmain(String[]args){

Ssytem.out.println("Hello ,World!");

}

}

Execute it and see, this is the output of jdk1.5:

java .lang.ExceptionInInitializerError

Causedby:java.lang.ArithmeticException:/byzero

atdebug.MyTest.(Test.java:3)

Exceptioninthread "main"

Please note that, like the exceptions generated when calling other methods, the exception is located in debug.MyTest.

Look again:

packagedebug;

p>

publicclassTest{

Test(){

inti=100/0;

}

publicstaticvoidmain(String[ ]args){

newTest();

}

}

jdk1.5 input:

Exceptioninthread"main"java.lang.ArithmeticException:/byzero

atdebug.Test.(Test.java:4)

atdebug.Test.main(Test.java:7) < /p>

The JVM does not locate the exception in the Test() constructor, but in debug.Test.

After we see these two methods, let's discuss these two "built-in initialization methods" in detail (I don't like to coin some

non-standard terms, but I really don't know what to call them canonically).

The built-in initialization method is a unique method used internally by the JVM for initialization, rather than a method provided to programmers to call. In fact,

The syntax "<>" is used in the source code. You can't even compile the program. This shows that initialization is controlled by the JVM rather than by the programmer.

Class initialization method:

I have not learned anywhere whether cl is the abbreviation of class, but this method is indeed used to initialize the "class"

Initialized. In other words it is used to initialize the static context.

When a class is loaded, the JVM will call built-in methods to initialize class members and static initialization blocks. Their

order follows the original text order of the source file.

We slightly add two lines of static statements:

packagedebug;

publicclassTest{

staticintx=0;

staticStrings="123";

static{

Strings1="456";

if(1==1)

thrownewRuntimeException();

}

publicstaticvoidmain(String[]args){

newTest();

}

}

Then decompile:

javap-cdebug.Test

Compiledfrom"Test.java"

publicclassdebug. Testextendsjava.lang.Object{

staticintx;

staticjava.lang.Strings;

publicdebug.Test();

Code:

0:aload_0

1:invokespecial#1;//Methodjava/lang/Object."":()V

4:return

publicstaticvoidmain(java.lang.String[]);

Code:

0:new#2;//classdebug/Test

3 :dup

4:invokespecial#3;//Method"":()V

7:pop

8:return

static{};

Code:

0:iconst_0

1:putstatic#4;//Fieldx:I

4 :ldc#5;//String123

6:putstatic#6;//Fields:Ljava/lang/String;

9:ldc#7;//String456

11:astore_0

12:new#8;//classjava/lang/RuntimeException

15:dup

16:invokespecial#9; //Methodjava/lang/RuntimeException."":()V

19:athrow

}

Here, we have to say that JDK has the javap function There is a BUG in the implementation. The 16 label in the static section indicates that the exception

occurred in the "" method, but in fact the output of this program when running is:

java.lang. ExceptionInInitializerError

Causedby:java.lang.RuntimeException

atdebug.Test.(Test.java:8)

Exceptioninthread"main"

But we can always understand that class initialization is performed in the original order defined in the source file.

First declare

staticintx;

staticjava.lang.Strings;

Then assign values ??to intx and Strings:

0:iconst_0 < /p>

1:putstatic#4;//Fieldx:I

4:ldc#5;//String123

6:putstatic#6;//Fields: Ljava/lang/String;

Execute Strings1="456" of the initialization block; generate a RuntimeException to throw

9:ldc#7;//String456

11:astore_0

12:new#8;//classjava/lang/RuntimeException

15:dup

16:invokespecial#9;//Methodjava/ lang/RuntimeException."":()V

19:athrow

What you need to understand is that the "" method is not only a class initialization method, but also an interface initialization method. Not all properties of interfaces

are inlined. Only interface constants that are directly assigned constant values ??will be inlined. And

[publicstaticfinal]doubled=Math.random()*100;

Such an expression needs to be calculated and must be initialized by the "" method in the interface.

Let's take a look at the instance initialization method ""

"" which is used to initialize the object when the object is created. When the object is created in HEAP, once the space is allocated in HEAP . Finally

the "" method will be called first. This method includes assignments to instance variables (not included in declarations) and initialization blocks, as well as constructor

method calls. If there are multiple overloaded constructors, each constructor will have a corresponding "" method.

Similarly, the order of instance variables and initialization blocks is also executed in the original order of the source file, and the code in the construction method is executed at the end:

packagedebug;

publicclassTest{

intx=0;

Strings="123";

{

Strings1="456";

//if(1==1)

//thrownewRuntimeException();

}

publicTest(){

< p>Stringss="789";

}

publicstaticvoidmain(String[]args){

newTest();

}

}

Results of javap-cdebug.Test:

Compiledfrom"Test.java"

publicclassdebug.Testextendsjava.lang.Object {

intx;

java.lang.Strings;

publicdebug.Test();

Code:

< p>0:aload_0

1:invokespecial#1;//Methodjava/lang/Object."":()V

4:aload_0

5 :iconst_0

6:putfield#2;//Fieldx:I

9:aload_0

10:ldc#3;//String123

12:putfield#4;//Fields:Ljava/lang/String;

15:ldc#5;//String456

17:astore_1

< p>18:ldc#6;//String789

20:astore_1

21:return

publicstaticvoidmain(java.lang.String[]); < /p>

Code:

0:new#7;//classdebug/Test

3:dup

4:invokespecial#8;/ /Method"":()V

7:pop

8:return

}

If in the same class, If a constructor calls another constructor, the corresponding "" method will call another "", but the instance variables and initialization blocks will be ignored, otherwise they will be executed multiple times. .

packagedebug;

publicclassTest{

Strings1=rt("s1");

Strings2="s2";

publicTest(){

s1="s1";

}

publicTest(Strings){

this( );

if(1==1)thrownewRuntime();

}

Stringrt(Strings){

returns; < /p>

}

publicstaticvoidmain(String[]args){

newTest("");

}

}

Result of decompilation:

Compiledfrom"Test.java"

publicclassdebug.Testextendsjava.lang.Object{

java. lang.Strings1;

java.lang.Strings2;

publicdebug.Test();

Code:

0:aload_0 < /p>

1:invokespecial#1;//Methodjava/lang/Object."":()V

4:aload_0

5:aload_0

6:ldc#2;//Strings1

8:invokevirtual#3;//Methodrt:(Ljava/lang/String;)Ljava/lang/String;

11:putfield#4;//Fields1:Ljava/lang/String;

14:aload_0

15:ldc#5;//Strings2

17 :putfield#6;//Fields2:Ljava/lang/String;

20:aload_0

21:ldc#2;//Strings1

23: putfield#4;//Fields1:Ljava/lang/String;

26:return

publicdebug.Test(java.lang.String);

Code :

0:aload_0

1:invokespecial#7;//Method"":()V

4:new#8;//classjava/ lang/RuntimeException

7:dup

8:invokespecial#9;//Methodjava/lang/RuntimeException."":()V

11:athrow

java.lang.Stringrt(java.lang.String);

Code:

0:aload_1

1:areturn < /p>

publicstaticvoidmain(java.lang.String[]);

Code:

0:new#10;//classdebug/Test

3:dup

4:ldc#11;//String

6:invokespecial#12;//Method"":(Ljava/lang/String;)V

9:pop

10:return

}

We once again saw a bug in javap implementation, although there is a "":( Ljava/lang/String;)V signature can explain

Each construction method corresponds to a different one, but the Runtime exception is still located in the ""()V method:

invokespecial #8;//Methodjava/lang/RuntimeException."":()V, but the

call in the main method is clearly "":(Ljava/lang/String;)V.

p>

But we see that since Test(Strings) calls Test();, "":(Ljava/lang/String;)V no longer performs operations on

instance variables and initialization blocks. First initialization:

publicdebug.Test(java.lang.String);

Code:

0:aload_0

1:invokespecial #7;//Method"":()V

4:new#8;//classjava/lang/RuntimeException

7:dup

8 :invokespecial#9;//Methodjava/lang/RuntimeException."":()V

11:athrow

And if the two constructors are independent of each other, each Instance variables and initialization block calls are executed before the constructor method is called:

packagedebug;

publicclassTest{

Strings1=rt("s1");

p>

Strings2="s2";

{

Strings3="s3";

}

publicTest() {

s1="s1";

}

publicTest(Strings){

if(1==1)

p>

thrownewRuntimeException();

}

Stringrt(Strings){

returns;

}

publicstaticvoidmain(String[]args){

newTest("");

}

}

Decompiled Result:

Compiledfrom"Test.java"

publicclassdebug.Testextendsjava.lang.Object{

java.lang.Strings1;

java.lang.Strings2;

publicdebug.Test();

Code:

0:aload_0

1:invokespecial#1 ;//Methodjava/lang/Object."":()V

4:aload_0

5:aload_0

6:ldc#2;// Strings1

8:invokevirtual#3;//Methodrt:(Ljava/lang/String;)Ljava/lang/String;

11:putfield#4;//Fields1:Ljava /lang/String;

14:aload_0

15:ldc#5;//Strings2

17:putfield#6;//Fields2:Ljava/ lang/String;

20:ldc#7;//Strings3

22:astore_1

23:aload_0

24:ldc #2;//Strings1

26:putfield#4;//Fields1:Ljava/lang/String;

29:return

publicdebug.Test( java.lang.String);

Code:

0:aload_0

1:invokespecial#1;//Methodjava/lang/Object."": ()V

4:aload_0

5:aload_0

6:ldc#2;//Strings1

8:invokevirtual# 3;//Methodrt:(Ljava/lang/String;)Ljava/lang/String;

11:putfield#4;//Fields1:Ljava/lang/String;

14:aload_0

15:ldc#5;//Strings2

17:putfield#6;//Fields2:Ljava/lang/String;

20 :ldc#7;//Strings3

22:astore_2

23:new#8;//classjava/lang/RuntimeException

26:dup

p>

27:invokespecial#9;//Methodjava/lang/RuntimeException."":()V

30:athrow

java.lang.Stringrt(java. lang.String);

Code:

0:aload_1

1:areturn

publicstaticvoidmain(java.lang.String[] );

Code:

0:new#10;//classdebug/Test

3:dup

4:ldc# 11;//String

6:invokespecial#12;//Method"":(Ljava/lang/String;)V

9:pop

10:return

}