Basic knowledge of

A diagram to understand the bytecode structure

Execution mode

  • Interpretation execution: the interpreter will interpret our sentences into binary codes that can be recognized by the machine for execution, such as Dalvik
  • Compile execution: the source program is translated into machine instructions by the compiler (responsible for translating the source program into target machine instructions), compiled –> link –> target executable, and then executed; That is to convert all source code into binary instructions at once in advance, that is, to generate an executable program, such as the old JIT, C++
  • Both: the new JIT

Regardless of the execution mode, the one thing that is consistent is that bytecode is a stack-based execution engine, as the following examples illustrate. Let’s take a look at its data structure

Execution data structure

Stack frame: Elements in a stack

  • Local variable table: Used to store local variables
  • Operand stack: Used to execute functions and inputs
  • Dynamic linking: Supports method reference conversion at run time
  • Return address: Method return is supported

Basic instructions

  • astore_n: The top reference value is stored in the NTH local variable
  • invokespecial:
  • invokevirtual: normal method call
  • dup: copies the top value of the stack and pushes it to the top
  • ldc: Pushes constants to the top of the stack
  • aload_n: Pushes the NTH variable of reference type to the top of the stack

The example analysis

Java source code
package jvm;
public class Language {
    public int count = 1;
    public String getContent(a) {
        return "hello world";
    }
    public String getContent2(a) {
        return "hello world 2"; }}public class Person {
    private final String name = "person";
    private final Language mLanguage = new Language();

    public void say(a) {
        System.out.println("Person say " +  mLanguage.getContent());
    }

    public static void main(String[] args) {
        Person person = newPerson(); person.say(); }}Copy the code
Javap -v Person output
public class jvm.Person
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC.ACC_SUPER
Constant pool# 1:= Methodref          #18.#33        // java/lang/Object."<init>":()V
   #2 = String             #34            // person
   #3 = Fieldref           #15.#35        // jvm/Person.name:Ljava/lang/String;
   #4 = Class              #36            // jvm/Language
   #5 = Methodref          #4.#33         // jvm/Language."<init>":()V
   #6 = Fieldref           #15.#37        // jvm/Person.mLanguage:Ljvm/Language;
   #7 = Fieldref           #38.#39        // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Class              #40            // java/lang/StringBuilder
   #9 = Methodref          #8.#33         // java/lang/StringBuilder."<init>":()V
  #10 = String             #41            // Person say
  #11 = Methodref          #8.#42         // java/lang/StringBuilder.append:(Ljava/lang/String;) Ljava/lang/StringBuilder;
  #12 = Methodref          #4.#43         // jvm/Language.getContent:()Ljava/lang/String;
  #13 = Methodref          #8.#44         // java/lang/StringBuilder.toString:()Ljava/lang/String;
  #14 = Methodref          #45.#46        // java/io/PrintStream.println:(Ljava/lang/String;) V
  #15 = Class              #47            // jvm/Person
  #16 = Methodref          #15.#33        // jvm/Person."<init>":()V
  #17 = Methodref          #15.#48        // jvm/Person.say:()V
  #18 = Class              #49            // java/lang/Object
  #19 = Utf8               name
  #20 = Utf8               Ljava/lang/String;
  #21 = Utf8               ConstantValue
  #22 = Utf8               mLanguage
  #23 = Utf8               Ljvm/Language;
  #24 = Utf8               <init>
  #25 = Utf8               ()V
  #26 = Utf8               Code
  #27 = Utf8               LineNumberTable
  #28 = Utf8               say
  #29 = Utf8               main
  #30 = Utf8               ([Ljava/lang/String;)V
  #31 = Utf8               SourceFile
  #32 = Utf8               Person.java
  #33 = NameAndType        #24: #25        // "<init>":()V
  #34 = Utf8               person
  #35 = NameAndType        #19: #20        // name:Ljava/lang/String;
  #36 = Utf8               jvm/Language
  #37 = NameAndType        #22: #23        // mLanguage:Ljvm/Language;
  #38 = Class              #50            // java/lang/System
  #39 = NameAndType        #51: #52        // out:Ljava/io/PrintStream;
  #40 = Utf8               java/lang/StringBuilder
  #41 = Utf8               Person say
  #42 = NameAndType        #53: #54        // append:(Ljava/lang/String;) Ljava/lang/StringBuilder;
  #43 = NameAndType        #55: #56        // getContent:()Ljava/lang/String;
  #44 = NameAndType        #57: #56        // toString:()Ljava/lang/String;
  #45 = Class              #58            // java/io/PrintStream
  #46 = NameAndType        #59: #60        // println:(Ljava/lang/String;) V
  #47 = Utf8               jvm/Person
  #48 = NameAndType        #28: #25        // say:()V
  #49 = Utf8               java/lang/Object
  #50 = Utf8               java/lang/System
  #51 = Utf8               out
  #52 = Utf8               Ljava/io/PrintStream;
  #53 = Utf8               append
  #54= Utf8 (Ljava/lang/String;) Ljava/lang/StringBuilder; #55 = Utf8               getContent
  #56 = Utf8               ()Ljava/lang/String;
  #57 = Utf8               toString
  #58 = Utf8               java/io/PrintStream
  #59 = Utf8               println
  #60= Utf8 (Ljava/lang/String;) V {private final java.lang.String name;
    descriptor: Ljava/lang/String;
    flags: ACC_PRIVATE, ACC_FINAL
    ConstantValue: String person

  private final jvm.Language mLanguage;
    descriptor: Ljvm/Language;
    flags: ACC_PRIVATE, ACC_FINAL

  public jvm.Person();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #2                  // String person
         7: putfield      #3                  // Field name:Ljava/lang/String;
        10: aload_0
        11: new           #4                  // class jvm/Language
        14: dup
        15: invokespecial #5                  // Method jvm/Language."<init>":()V
        18: putfield      #6                  // Field mLanguage:Ljvm/Language;
        21: return
      LineNumberTable:
        line 3: 0
        line 5: 4
        line 6: 10

  public void say(a);
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=1, args_size=1
        // Get a static object
         0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
         // The new three brothers appear again
         3: new           #8                  // class java/lang/StringBuilder
         6: dup
         7: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
        // Push constant #10 ('Person Say') in the constant pool to the top of the stack
        10: ldc           #10                 // String Person say
        // Call method stringBuilder.append ()
        12: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;) Ljava/lang/StringBuilder;
        // Push this to the top of the stack in order to call getField
        15: aload_0
        // Fetch #6 (mLanguage) from the field set to the top of the stack
        16: getfield      #6                  // Field mLanguage:Ljvm/Language;
        #56 -> mlanguage.getContent (): String
        19: invokevirtual #12                 // Method jvm/Language.getContent:()Ljava/lang/String;
        Builder.append (): StringBuilder In fact, the default English comments are already written clearly
        22: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;) Ljava/lang/StringBuilder;
        25: invokevirtual #13                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        28: invokevirtual #14                 // Method java/io/PrintStream.println:(Ljava/lang/String;) V
        31: return
      LineNumberTable:
        line 9: 0
        line 10: 31

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
        // New, DUP, invokespecial is a classical combination, which illustrates that new is not an atomic operation in nature
        // Create an object reference (see constant pool table for object #15) and stack it
         0: new           #15                 // class jvm/Person
         // copy the object reference into the stack
         3: dup
         // Call the init method of Person (also visible here via the constant pool table)
         4: invokespecial #16                 // Method "<init>":()V
         // store at the top of the stack (a reference to Person at this point) to the first local variable table, which is actually assigned to the local variable Person
         7: astore_1
         // Load the local variable table with index 1 at the top of the stack (index 0 is this), which is ready for the method call
         8: aload_1
         // Call the method specified in #17, where the method is say()
         9: invokevirtual #17                 // Method say:()V
        12: return
      LineNumberTable:
        line 13: 0
        line 14: 8
        line 15: 12
}
SourceFile: "Person.java"
Copy the code