001. Analysis of operation principle of JAVA program

Posted by shawngoldw on Thu, 21 Nov 2019 19:38:35 +0100

1. First look at the structure of the JVM runtime data area

  • Thread exclusive: Each thread has its own space that is created and destroyed with the thread lifecycle.
  • Thread sharing: All threads have access to this memory data, which is created and destroyed with the virtual machine GC.
  • JVM stores loaded class information, constants, static variables, compiled code, and so on.

Method Area

  • This is a logical area in the virtual machine specification.
  • The implementation is based on different virtual machines.
  • For example, HotSpot for oracle is in the permanent generation of the method area in java7, java8 is in the metadata space, and this area is managed through the GC mechanism.

Heap memory

  • Heap memory can be divided into:
    • Older generations
    • Cenozoic era
      • Eden
      • From Survivor
      • To Survivor
  • Created at JVM startup to hold instances of objects.
  • The garbage collection period mainly manages heap memory.If it is full, an OutOfMemoryError will appear.

VM Stack

  • Each thread has a private space in this space.
  • A thread stack consists of multiple stack frames.
  • A thread executes one or more methods, one corresponding to a stack frame.
  • The contents of the stack frame include: local variable table, operand stack, dynamic link, method return address, additional information, and so on.
  • StackOverflowError is thrown if stack memory exceeds the default maximum of 1M.

Native Method Stack

  • Similar to the virtual machine stack functionality, the virtual machine stack is prepared for the virtual machine to execute JAVA methods, and the local method stack is prepared for the virtual machine to use the Native local method.
  • The VM specification does not specify a specific implementation, which is implemented by different VM vendors.
  • The implementation of the virtual machine stack in the HotSpot virtual machine is the same as that of the local method stack.Similarly, StackOverflowError will be thrown when the size is exceeded.

Program Counter Register

  • Records where the current thread executes the byte code, stores the byte code instruction address, and if the Native method is executed, the counter value is empty.
  • Each thread has a private space in this space, which takes up little memory space.
  • The CPU executes instructions from only one thread at a time.JVM multithreading switches and allocates CPU execution time in turn.In order to restore the correct execution location after thread switching, program counters are required.

2. Next, let's look at the byte code files that we often refer to

1. Get a test code first

public class Demo1 {
    public static void main(String[] args) {
        int x = 500;
        int y = 100;
        int a = x / y;
        int b = 50;
        System.out.println(a + b);
    }
}

2. Compile and generate class files

# Compile
javac Demo1.java
# view file contents
javap -v Demo1.class > Demo.txt

3. Next, let's see what the Demo.txt file is all about.

Official description of the class file ( https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.1)

Classfile /Users/shadowolf/Demo1.class
  Last modified 2019-11-7; size 414 bytes
  MD5 checksum ae6fa820973681b35609c75631cb255b
  Compiled from "Demo1.java"
public class Demo1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #5.#14         // java/lang/Object."<init>":()V
   #2 = Fieldref           #15.#16        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Methodref          #17.#18        // java/io/PrintStream.println:(I)V
   #4 = Class              #19            // Demo1
   #5 = Class              #20            // java/lang/Object
   #6 = Utf8               <init>
   #7 = Utf8               ()V
   #8 = Utf8               Code
   #9 = Utf8               LineNumberTable
  #10 = Utf8               main
  #11 = Utf8               ([Ljava/lang/String;)V
  #12 = Utf8               SourceFile
  #13 = Utf8               Demo1.java
  #14 = NameAndType        #6:#7          // "<init>":()V
  #15 = Class              #21            // java/lang/System
  #16 = NameAndType        #22:#23        // out:Ljava/io/PrintStream;
  #17 = Class              #24            // java/io/PrintStream
  #18 = NameAndType        #25:#26        // println:(I)V
  #19 = Utf8               Demo1
  #20 = Utf8               java/lang/Object
  #21 = Utf8               java/lang/System
  #22 = Utf8               out
  #23 = Utf8               Ljava/io/PrintStream;
  #24 = Utf8               java/io/PrintStream
  #25 = Utf8               println
  #26 = Utf8               (I)V
{
  public Demo1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=5, args_size=1
         0: sipush        500
         3: istore_1
         4: bipush        100
         6: istore_2
         7: iload_1
         8: iload_2
         9: idiv
        10: istore_3
        11: bipush        50
        13: istore        4
        15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        18: iload_3
        19: iload         4
        21: iadd
        22: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
        25: return
      LineNumberTable:
        line 3: 0
        line 4: 4
        line 5: 7
        line 6: 11
        line 7: 15
        line 8: 25
}
SourceFile: "Demo1.java"

Classfile

Classfile /Users/shadowolf/Demo1.class
  Last modified 2019-11-7; size 414 bytes
  MD5 checksum ae6fa820973681b35609c75631cb255b
  Compiled from "Demo1.java"
  • Mainly records some file information, including file local address, file size, last update time, MD5 check, compilation source, etc.

public class Demo1

public class Demo1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
  • This section describes some of the information compiled.

  • Major version: major version number, minor version: minor version number, below is the corresponding relationship of versions.

    JDK Version major.minor version
    1.1 45
    1.2 46
    1.3 47
    1.4 48
    1.5 49
    1.6 50
    1.7 51
    1.8 52
    • You can count down the rest of yourself.
  • Flags: Access flag.The following is a list of access flags and their explanations

    Flag Name Flag Value Meaning
    ACC_PUBLIC 0x0001 Is it a public type
    ACC_FINAL 0x0010 Is declared final, only classes can be set
    ACC_SUPER 0x0020 Whether invokespecial byte code directives are allowed or not, this flag is true for classes compiled after JDK12
    ACC_INTERFACE 0x0200 Flag this is an interface
    ACC_ABSTRACT 0x0400 Is Abstract type, true for interface or abstract class, false for other values
    ACC_SYNTHETIC 0x1000 Marks that this class is not user generated
    ACC_ANNOTATION 0x2000 Identify this is a comment
    ACC_ENUM 0x4000 Identify this is an enumeration

Constant pool

Constant pool:
   #1 = Methodref          #5.#14         // java/lang/Object."<init>":()V
   #2 = Fieldref           #15.#16        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Methodref          #17.#18        // java/io/PrintStream.println:(I)V
   #4 = Class              #19            // Demo1
   #5 = Class              #20            // java/lang/Object
   #6 = Utf8               <init>
   #7 = Utf8               ()V
   #8 = Utf8               Code
   #9 = Utf8               LineNumberTable
  #10 = Utf8               main
  #11 = Utf8               ([Ljava/lang/String;)V
  #12 = Utf8               SourceFile
  #13 = Utf8               Demo1.java
  #14 = NameAndType        #6:#7          // "<init>":()V
  #15 = Class              #21            // java/lang/System
  #16 = NameAndType        #22:#23        // out:Ljava/io/PrintStream;
  #17 = Class              #24            // java/io/PrintStream
  #18 = NameAndType        #25:#26        // println:(I)V
  #19 = Utf8               Demo1
  #20 = Utf8               java/lang/Object
  #21 = Utf8               java/lang/System
  #22 = Utf8               out
  #23 = Utf8               Ljava/io/PrintStream;
  #24 = Utf8               java/io/PrintStream
  #25 = Utf8               println
  #26 = Utf8               (I)V
  • Constant pool.

  • For a more detailed understanding of constant pools, check out the blog ( http://softlab.sdut.edu.cn/blog/subaochen/2018/12/java-class%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%EF%BC%9A%E5%B8%B8%E9%87%8F%E6%B1%A0/)

  • List the constants

    type describe
    CONSTANT_utf8_info UTF-8 Encoded String
    CONSTANT_Integer_info Integer Literal Quantity
    CONSTANT_Float_info Floating Point Literal Quantity
    CONSTANT_Long_info Long Integer Literal Quantity
    CONSTANT_Double_info Double Precision Floating Point Literal Quantity
    CONSTANT_Class_info Symbolic references to classes or interfaces
    CONSTANT_String_info String Type Literal Quantity
    CONSTANT_Fieldref_info Symbolic reference to field
    CONSTANT_Methodref_info Symbolic references to methods in classes
    CONSTANT_InterfaceMethodref_info Symbolic references to methods in interfaces
    CONSTANT_NameAndType_info Symbolic references to fields or methods
    CONSTANT_MethodType_info Flag Method Type
    CONSTANT_MethodHandle_info Representation Handle
    CONSTANT_InvokeDynamic_info Represents a dynamic method call point

Construction method

public Demo1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
  • In Demo1, we did not write a constructor.

  • Thus, when no constructor is defined, there is an implicit parameterless constructor.

  • Descriptor: ()V ->The understanding of this is that the input is null and the return value is void

Entry function: main function

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=5, args_size=1
         0: sipush        500
         3: istore_1
         4: bipush        100
         6: istore_2
         7: iload_1
         8: iload_2
         9: idiv
        10: istore_3
        11: bipush        50
        13: istore        4
        15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        18: iload_3
        19: iload         4
        21: iadd
        22: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
        25: return
      LineNumberTable:
        line 3: 0
        line 4: 4
        line 5: 7
        line 6: 11
        line 7: 15
        line 8: 25
  • Let's look at the execution order of the entire program

    • 0: sipush 500: Push 500 into the operand stack

      Sequence Number Local variable table
      0 args
      Operand stack
      500
    • 3: istore_1: Save 500 to local variable table 1

      Sequence Number Local variable table
      0 args
      1 500
      Operand stack
    • 4: bipush 100: Push 100 into the operand stack

      Sequence Number Local variable table
      0 args
      1 500
      Operand stack
      100
    • 6: istore_2: Save 100 to the location of local variable table 2

      Sequence Number Local variable table
      0 args
      1 500
      2 100
      Operand stack
    • 7: iload_1, 8: iload_2: Push data from local variable locations 1 and 2 into the operand stack

      Sequence Number Local variable table
      0 args
      1 500
      2 100
      Operand stack
      100
      500
    • 9: idiv: divides and pushes the result into the operand stack

      Sequence Number Local variable table
      0 args
      1 500
      2 100
      Operand stack
      5
    • 10: istore_3: Save 5 (500/100) to the location of local variable table 3

      Sequence Number Local variable table
      0 args
      1 500
      2 100
      3 5
      Operand stack
    • 11: bipush 50: Push 50 into the operand stack

      Sequence Number Local variable table
      0 args
      1 500
      2 100
      3 5
      Operand stack
      50
    • 13: iStore 4: Save 50 to the location of local variable table 4 |Sequence Number|Local Variable Table| | --- | --- | | 0 | args | | 1 | 500 | | 2 | 100 | | 3 | 5 | | 4 | 50 |

      Operand stack
    • 15: getstatic #2 // Field java/lang/System.out: Ljava/io/PrintStream; #2 from the constant pool is pushed into the operand stack

      Sequence Number Local variable table
      0 args
      1 500
      2 100
      3 5
      4 50
      Operand stack
      #2
    • 18: iload_3: Push data from 3 locations in the local variable table (5) into the operand stack

      Sequence Number Local variable table
      0 args
      1 500
      2 100
      3 5
      4 50
      Operand stack
      5
      #2
    • 19: Iload 4: Push data (50) from 4 locations in the local variable table into the operand stack

      Sequence Number Local variable table
      0 args
      1 500
      2 100
      3 5
      4 50
      Operand stack
      50
      5
      #2
    • 21: iadd: Adds the first two elements of the stack and pushes the execution result (50+5=55) into the operand stack

      Sequence Number Local variable table
      0 args
      1 500
      2 100
      3 5
      4 50
      Operand stack
      55
      #2
    • 22: invokevirtual #3 // Method java/io/PrintStream.println:(I)V: JVM creates a new stack frame based on the description of this method. The parameters of the method pop up from the operand stack and push into the virtual machine stack. The virtual machine stack then starts executing the top stack frame of the virtual machine stack.

    • 25: return: Execution complete, return to continue the main method, return, main method end.

    • At this point, the execution of our entire main function is explained.

3. Look at the running analysis of the overall function

1. Load information into method area

2. JVM creates a thread to execute

3. Execute main function

  • This section has been analyzed above and is not repeated here.

Topics: Programming Java jvm Oracle JDK