• concept
  • Constant pool
    • The benefits of constant pools
  • Class constant pool in the Class file
    • Constant pool
      • Run-time constant pool
  • Wrapper class constant pool Object pool
  • Packing and unpacking in Java
    • assignment
    • Method call
    • Method operation
  • reference

concept

What is a constant? Many of you are likely to blurt out that final variables are constants or strings defined at compile time. (String constant)

But this statement is not exact because, to be exact, constants are member variables that are final! Constants are loaded into the class’s constant pool at compile time.

Static variables can only be static variables. Local variables that are modified with final (within a method) can also be called immutable variables. (Stored on the stack)

Constant pool

Constant pools in Java actually come in two forms: static constant pools and runtime constant pools.

  • Static constant pool: a constant pool in a *. Class file. A constant pool in a class file contains not only string (number) literals, but also information about classes and methods, which occupies most of the space in a class file. (Compile time)

  • Runtime constant pool: After class loading, the JVM loads the constant pool from the class file into memory and stores it in the method area. (runtime) Supplement: Constants in the runtime constant pool are basically derived from the constant pool in each class file. (that is, each class file has a corresponding constant pool)

The benefits of constant pools

Constant pool is to avoid frequent creation and destruction of objects that affect system performance, and it realizes object sharing. The string constant pool, for example, puts all string literals into one constant pool at compile time.

(1) Saving memory space: all the same string constants in the constant pool are merged and occupy only one space.

(2) Save runtime: == is faster than equals() when comparing strings. For two reference variables, only == is used to determine whether the references are equal, which can also determine whether the actual values are equal

The meaning of double equals == When a double equals sign is applied between basic data types, it is their numeric values that are compared. A double equal sign is applied between compound data types (classes) to compare where they reside in memory. (Reference address)

        String hello="helloMoto";   
        String hello2="helloMoto";  Copy the code

For example, we define hello and hello2, and the string constant “helloMoto” does not exist in the string constant pool. So we first create a “helloMoto” string object in the string constant pool, and hello points to the “helloMoto” string object in the string constant pool. The first line of code, Hello2, first looks for “helloMoto” in the constant pool, finds it already exists, and points directly to the “helloMoto” string object in the string constant pool. (String object exploration)

Class constant pool in the Class file

  • Magic Number: The first four bytes of a Class file are called the Magic Number. Its sole function is to determine whether the file is a Class file acceptable to the VIRTUAL machine. Many file storage standards use magic numbers for identification. Using magic numbers rather than extensions for identification is mainly for security reasons, since file extensions can be changed at will. The magic number in the Class file has a romantic flavor of 0x CAFEBABE which is one of the reasons Java is the coffee icon and trademark name.

  • Version number: The version number of the Class file is stored immediately after the four magic number stanzas: bytes 5 and 6 are minor version numbers, and bytes 7 and 8 are major version numbers.

  • Constant pool: Following the primary and secondary version numbers is the entry to the constant pool, which can be understood as a repository of resources in the Class file. It is the data type most associated with other items in the Class file structure, and is one of the data items that occupy the largest space in the Class file. A constant pool in a Class file can be called a static constant pool until the Class is loaded into memory. The entry identifies the number of constants in the constant pool with two bytes.

We use the hex editor WinHex to open the Class file

public class Test2 { public static void main(String[] args) { String hello="helloMoto"; }}Copy the code



The constant pool contains various types of constants, each of which has its own type, and each has its own storage specification. This article focuses on string constants, which begin with 01 (1 byte), followed by 2 bytes to record the length of the string, and then the actual contents of the string.



Constant pool

The constant pool is used to store two main types of constants: literals and symbolic references

Literals are equivalent to Java language level constants, such as text strings, constant values declared final (member variables), and so on.

Symbolic references are a compilation principle and include three types of constants:

  • Fully qualified names of classes and interfaces

  • Field name and descriptor

  • Method name and descriptor

Run-time constant pool

The final memory layout of each method or field is not stored in the Class file, so symbolic references to these fields or methods cannot be used directly by the virtual machine without obtaining the actual memory entry address without running time conversion. This content will be stored in the runtime constant pool when the class is loaded into the method area.

Runtime constant pool relative to the CLass file constant pool (static constant pool) another important feature is dynamic, the Java language does not require constant must only compile time to produce, is not preset constant pool into the CLass file content can enter method area runtime constant pool, runtime might also put new constants in a pool, One feature that developers use most is the Intern () method of the String class.

Wrapping class constant pool (object pool)

Basic types in the Java wrapper classes are mostly true constant pool technology, namely, Byte, Short, Integer, Long, Character, and Boolean; Float,Double

Integer i1 = 127; Integer i2 = 127; System.out.println(i1==i2); //true Integer i3 = 128; Integer i4 = 128; System.out.println(i3==i4); //falseCopy the code

For the above two pieces of code different results we can trace the Integer source code

//Integer

    public static Integer valueOf(int i) {
        if (i >= -128 && i <= 127)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }Copy the code

You can see that if the value is in the [-128,127] field, the IntegerCache class is used to cache the data, similar to string constant pools. So if a value is assigned outside the range, a new Integer object is created. (The advantage is that if Integer is used frequently and the value is in [-128,127], new Integer objects will not be created repeatedly.)

But there is no implementation of a constant pool (object pool) for the wrapper classes of the two basic data types Double and Float.

//Double


    public static Double valueOf(double d) {
        return new Double(d);
    }Copy the code

Packing and unpacking in Java

Basic data types A wrapper class
Int (4 bytes) Integer
Byte (1 byte) Byte
Short (2 bytes) Short
Long (8 bytes) Long
Float (4 bytes) Float
Double (8 bytes) Double
Char (2 bytes) Character
Boolean (1 byte) Boolean

assignment

  • If you want to generate an Integer object with a value of 10, you just need to do this:
Integer i = 10;Copy the code

This process automatically creates the corresponding Integer object based on the value, which is called boxing.

  • Split open a case
Integer i = 10; Int n = I; / / split open a caseCopy the code

Simply put, boxing automatically converts the base data type to the wrapper type; Unpacking automatically converts wrapper types to primitive data types.

Method call

public class Test2 { public static void main(String[] args) { int result = print(5); } private static int print(Integer a) {system.out.println ("a==" + a); return a; // Returns an int. Integer is automatically unpacked to an int. } } //a==5Copy the code

Method operation

public class Test2 { public static void main(String[] args) { Integer sum = 0; for (int i = 1000; i < 5000; I ++) {sum += I; sum += I; }}}Copy the code

Sum += I = sum+ I = sum+ I = sum+ I = sum+ I = sum+ I = sum+ I = sum+ I = sum+ I = sum+ I = sum+ I The internal changes are as follows

int result = sum.intValue() + i;
Integer sum = new Integer(result);Copy the code

Since the sum declared here is of type Integer, the above loop creates approximately 4000 useless Integer objects, which can degrade program performance and increase garbage collection efforts in such a large loop. So when we program, we need to be aware of this and declare variable types correctly to avoid performance problems caused by automatic boxing.

reference

Dreamworks’ brief book takes a deep look at the boxing and unboxing techniques in Java