Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the essence of Java constant and what are the three constant pools

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail about the nature of Java constants and what the three constant pools are. The content of the article is of high quality, so the editor will share it for you as a reference. I hope you will have a certain understanding of the relevant knowledge after reading this article.

Constant pools in Java are divided into three forms: static constant pool, string constant pool, and runtime constant pool.

Static constant pool

The so-called static constant pool, that is, the constant pool in the * .class file, the constant pool in the class file contains not only literal strings (numbers), but also information about classes and methods, which takes up most of the space in class files. This constant pool is mainly used to store two types of constants: literal (Literal) and symbolic citation (Symbolic References). Literals are equivalent to the concepts of constants at the Java language level, such as text strings, constant values declared as final, and so on. Symbolic references belong to the concept of compilation principles, including the following three types of constants:

Fully qualified field names and descriptor method names and descriptors for classes and interfaces

On the other hand, the running constant pool is that the jvm virtual machine loads the constant pool in the class file into memory and saves it in the method area after completing the class loading operation. We often refer to the constant pool in the method area.

Running constant pool relative to the Class file constant pool another important feature is dynamic, Java language does not require that constants must be generated only at the compilation time, that is, not preset into the constant pool in the class file can enter the method area run constant pool, during the run may also put new constants into the pool, this feature is often used by developers is the String class intern () method.

String's intern () method looks up whether there is an equal equivalent string in the constant pool, returns a reference to the string if it does, and adds its own string to the constant pool if not.

From this point of view, it is better to explore the meaning of constants through static constant pools, that is, constant pools in * .class files.

Let's look at a piece of code.

Public class Main {

Public static void main (String [] args) {

System.out.println (Father.str);}} class Father {

Public static String str = "Hello,world"; static {

System.out.println ("Father static block")

}}

The output is

Look at another one:

Package com.company;public class Main {

Public static void main (String [] args) {

System.out.println (Father.str);}} class Father {public static final String str = "Hello,world"; static {

System.out.println ("Father static block")

}}

Results:

There's only one.

Are you surprised to find out?

Let's decompile the code block of the second demonstration.

D:\ CodePractise\ untitled\ out\ production\ untitled\ com\ company > javap-c Main.classCompiled from "Main.java" public class com.company.Main {

Public com.company.Main ()

Code: 0: aload_0 1: invokespecial # 1

/ / Method java/lang/Object. "": () V 4: return public static void main (java.lang.String [])

Code: 0: getstatic # 2

/ / Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc # 4

/ / String Hello,world 5: invokevirtual # 5

/ / Method java/io/PrintStream.println: (Ljava/lang/String;) V 8: return}

Here is a Main () is the constructor, and below is the main method.

0: getstatic # 2 corresponds to System.out3: ldc # 4 corresponds directly to Hello,world. The determined value is not taken out of the Father class.

Ldc means to push a constant value of type int,float or String from the constant pool to the top of the stack

I can't believe it didn't! Even if you delete the Father.class file, the code can still run it and it has nothing to do with the Father class.

In fact, at compile time, the constant is stored in the constant pool of the class where the method calling the constant is called.

You can see from this example that the str here is a constant, and the method that calls this constant is the main method, the class in which the main method is located is Main, that is, after compilation, str is placed in the constant pool of this class.

In essence, the calling class does not refer directly to the class that defines the constant, so it does not trigger the initialization of the class that defines the constant

The initialization of the class involves the loading mechanism of the class. I don't want to say that we have to talk about it for the time being.

String constant pool (string pool is also called string literal pool)

The contents of the global string pool are loaded in the class, verified, and after the preparation phase, the string object instance is generated in the heap, and then the reference value of the string object instance is stored in string pool (remember: string pool stores the reference value rather than the specific instance object, which is stored in a piece of space opened up in the heap. ).

The location of the string constant pool is not accurate in JDK6.0 and previous versions, where the string constant pool is placed in the Perm Gen area (that is, the method area); in the JDK7.0 version, the string constant pool is moved to the heap.

The string pool function implemented in HotSpot VM is a StringTable class, which is a hash table that contains references to resident strings (that is, what we often call double quotation marks) (rather than the resident string instance itself), that is, some string instances in the heap are given the status of "resident string" after they are referenced by this StringTable. This StringTable has only one instance of each HotSpot VM and is shared by all classes.

Go back to the running constant pool (runtime constant pool)

When jvm executes a class, it must go through loading, connecting and initializing, and the connection includes three stages: verification, preparation and parsing.

When the class is loaded into memory, jvm stores the contents of the static constant pool into the runtime pool, so the runtime pool also has one for each class.

Static constant pools store literals and symbolic references, that is, instead of storing instances of objects, they store symbolic references to objects. After parsing (resolve), that is, replacing the symbol reference with a direct reference, the parsing process will query the string constant pool, that is, the StringTable mentioned above, to ensure that the string referenced by the runtime constant pool is consistent with that referenced in the string constant pool.

Let's look at an example.

Import java.util.UUID;public class Test {

Public static void main (String [] args) {

System.out.println (TestValue.str)

}} class TestValue {

Public static final String str = UUID.randomUUID () .toString ()

Static {

System.out.println ("TestValue static code")

}}

Results:

Since the str of the declaration itself is constant, the key point is whether the value of this constant can be determined at compile time. Obviously, the example here is uncertain at compile time. It needs to be determined at run time, which requires the target class to be initialized

When the value of a constant is not determinable during compilation, then its value will not be placed in the constant pool of the calling class. This will result in active use of the constant's class while the program is running, obviously causing the class to be initialized. (this involves the loading mechanism of the class, which will be marked here later)

Decompiler to explore:

Compiled from "Test.java" class com.leetcodePractise.tstudy.TestValue {public static final java.lang.String str; com.leetcodePractise.tstudy.TestValue (); Code: 0: aload_0 1: invokespecial # 1

/ / Method java/lang/Object. "": () V 4: return static {}; Code: 0: invokestatic # 2

/ / Method java/util/UUID.randomUUID: () Ljava/util/UUID; 3: invokevirtual # 3

/ / Method java/util/UUID.toString: () Ljava/lang/String; 6: putstatic # 4

/ / Field str:Ljava/lang/String; 9: getstatic # 5

/ / Field java/lang/System.out:Ljava/io/PrintStream; 12: ldc # 6

/ / String TestValue static code 14: invokevirtual # 7

/ / Method java/io/PrintStream.println: (Ljava/lang/String;) V 17: return}

Obviously, the TestValue class will be initialized.

After the constant introduction, here are some notes on decompilation and mnemonics.

Package com.company;public class Main {public static void main (String [] args) {System.out.println (Father.str); System.out.println (Father.s);}} class Father {public static final String str = "Hello,world"; public static final short s = 6; static {System.out.println ("Father static block");}}

Public class com.company.Main {public com.company.Main (); Code: 0: aload_0 1: invokespecial # 1

/ / Method java/lang/Object. "": () V 4: return public static void main (java.lang.String []); Code: 0: getstatic # 2

/ / Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc # 4

/ / String Hello,world 5: invokevirtual # 5

/ / Method java/io/PrintStream.println: (Ljava/lang/String;) V 8: getstatic # 2 / / Field java/lang/System.out:Ljava/io/PrintStream; 11: bipush 6 13: invokevirtual # 6

/ / Method java/io/PrintStream.println: (I) V 16: return}

Bipush means to push the constant value of a single byte to the top of the stack

Re-join

Package com.company;public class Main {

Public static void main (String [] args) {

System.out.println (Father.str)

System.out.println (Father.s)

System.out.println (Father.t)

}} class Father {public static final String str = "Hello,world"

Public static final short s = 6

Public static final int t = 128; static {

System.out.println ("Father static block")

}}

Do decompilation

Public class com.company.Main {public com.company.Main (); Code: 0: aload_0 1: invokespecial # 1

/ / Method java/lang/Object. "": () V 4: return public static void main (java.lang.String []); Code: 0: getstatic # 2 / / Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc # 4

/ / String Hello,world 5: invokevirtual # 5

/ / Method java/io/PrintStream.println: (Ljava/lang/String;) V 8: getstatic # 2

/ / Field java/lang/System.out:Ljava/io/PrintStream; 11: bipush 6 13: invokevirtual # 6

/ / Method java/io/PrintStream.println: (I) V 16: getstatic # 2

/ / Field java/lang/System.out:Ljava/io/PrintStream; 19: sipush 128 22: invokevirtual # 6

/ / Method java/io/PrintStream.println: (I) V 25: return}

Sipush means to push a short integer constant value (- 32768mm 32767) to the top of the stack

Make changes again

Package com.company;public class Main {public static void main (String [] args) {System.out.println (Father.str); System.out.println (Father.t);}} class Father {public static final String str = "Hello,world"; public static final int t = 1; static {System.out.println ("Father static block");}}

Public class com.company.Main {

Public com.company.Main ()

Code: 0: aload_0 1: invokespecial # 1

/ / Method java/lang/Object. "": () V 4: return public static void main (java.lang.String [])

Code: 0: getstatic # 2

/ / Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc # 4

/ / String Hello,world 5: invokevirtual # 5

/ / Method java/io/PrintStream.println: (Ljava/lang/String;) V 8: getstatic # 2

/ / Field java/lang/System.out:Ljava/io/PrintStream; 11: bipush 6 13: invokevirtual # 6

/ / Method java/io/PrintStream.println: (I) V 16: getstatic # 2

/ / Field java/lang/System.out:Ljava/io/PrintStream; 19: sipush 128 22: invokevirtual # 6

/ / Method java/io/PrintStream.println: (I) V 25: return} D:\ CodePractise\ untitled\ out\ production\ untitled\ com\ company > javap-c Main.classCompiled from "Main.java" public class com.company.Main {public com.company.Main (); Code: 0: aload_0 1: invokespecial # 1

/ / Method java/lang/Object. "": () V 4: return public static void main (java.lang.String []); Code: 0: getstatic # 2

/ / Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc # 4

/ / String Hello,world 5: invokevirtual # 5

/ / Method java/io/PrintStream.println: (Ljava/lang/String;) V 8: getstatic # 2

/ / Field java/lang/System.out:Ljava/io/PrintStream; 11: iconst_1 12: invokevirtual # 6

/ / Method java/io/PrintStream.println: (I) V 15: return}

This place has become iconst_1.

Iconst 1 means that int type 1 is pushed to the top of the stack (iconst_m1-iconst_5). When it is greater than 5, it becomes bipushm1, which corresponds to-1.

On the nature of Java constants and what the three constant pools are shared here, I hope that the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report