[JVM] LXF Deep Understanding of JVM Theme (1-4)

Posted by BlaineSch on Tue, 13 Aug 2019 12:19:34 +0200

Links to the original text: https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513667&idx=1&sn=26d2585a465a0cce1595b88a0fe959b3&chksm=80d67a80b7a1f39643d16fab2174a6048359a1f161ff882d6172178eabe22c3584c0f6e82579&scene=21#wechat_redirect

Articles Catalogue

Preface

========================================================================================================
I can't guarantee that everything I write is right, but at least I can guarantee that every sentence, every line of code has been carefully deliberated and carefully considered. Behind each article, I hope to see my attitude towards technology and life.

I believe what Jobs said is that only those who are crazy enough to think they can change the world can really change the world. In the face of pressure, I can fight at night and never sleep; in the face of difficulties, I am willing to face difficulties and never shrink back!

In fact, what I want to say is that I am just a programmer, and this is the whole of my pure life now.

=========================================================================================================

This article is mainly used to sort out the learning context of LXF_JVM project.

Deeply Understanding the Beginning of JVM Virtual Machine: Introduction to JVM and Knowledge Context

The blogger referred to this article: It's no use learning Java Virtual Machine? Listen to what the parties say!

Deep Understanding of JVM Virtual Machine 1: JVM Memory Model and the Disappearance of Permanent Generation

Deeply Understanding the Basic Principles and Algorithms of JVM Virtual Machine 2: JVM Garbage Recycling

The blogger refers to the following four articles:

Java GC Series (1): Introduction to Garbage Recycling

  • Java Key Terminology
  • Java HotSpot Virtual Machine
  • JVM Architecture
  • Java heap memory

Java GC Series (2): How does Java garbage collection work?

  • Start Java garbage collection
  • Java garbage collection process
  • The End of Instances in Garbage Recycling
  • When do objects meet garbage collection requirements?
  • GC Scope sample program
  • A sample program of GC OutOfMemoryError

Java GC Series (3): Types of garbage collectors

  • Java has four types of garbage collectors (GC):
    • Serial GC
    • Parallel GC
    • Concurrent Markup Scanning Garbage Collector (CMS GC)
    • G1 garbage collector (G1 GC)
  • JVM configuration for garbage collection
    • Running garbage collector types
    • Optimal configuration of GC
    • Examples of using JVM GC parameters

Java GC Series (3): Garbage Recycling Monitoring and Analysis

  • Java GC Monitoring and Analysis Tool
  • Java VisualVM
    • Start Visual VM
    • Install Visual GC Plug-ins
    • Monitoring GC

1. The triggering time of various GC (When)

  • GC type
  • Trigger time (condition)

2. JVM garbage determination algorithm

  1. Reference Counting
  2. Reachability Analysis Algorithms (Root Search Algorithms)

3. Four citations

  1. Strong citation
  2. Soft citation
  3. Weak citation
  4. Virtual reference

4. JVM garbage collection algorithm

  1. Mark-Sweep
  2. Copying algorithm
  3. Mark-Compact
  4. Generational Collection
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.log4j.Logger;
 
public class HelloWorld {
    private static Logger LOGGER = Logger.getLogger(HelloWorld.class.getName());
    public void sayHello(String message) {
        SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.YYYY");
        String today = formatter.format(new Date());
        LOGGER.info(today + ": " + message);
    }
}

Deep Understanding of JVM Virtual Machine 3: Garbage Recycler Details

From _____________ Javadoop Home Page

Javadoop Home Page: Here, a good Java programmer wrote many high-quality articles

This article mainly translates the first four chapters of the white paper Memory Management in the Java HotSpot Virtual Machine.

I. Garbage Collection Concept

  • Ideal features of garbage collectors
  • Design trade-offs
  • What is stop the world?
  • performance index
  • Introduction to Generation Collection

Garbage Collector in J2SE 5.0 HotSpot JVM

  • HotSpot Generation
  • Types of garbage collection
  • Fast allocation
  • Serial Collector
  • parallel collector
  • parallel compacting collector
  • CMS Collector

Introduction of G1 Garbage Collector

1. G1 Overview
2. G1 workflow
  • Young Generation Collection

  • Old GC/Concurrent Marker Period

  • Full GC

    1.concurrent mode failure

    2. Failure to Promote

    3. Evacuation failure

    4. Failure to allocate large objects

3. G1 parameter configuration and best practices
  • Introduction of parameters
  • Java GC Monitoring and Analysis Tool

Deep Understanding of JVM Virtual Machine 4: Java class Introduction and Parsing Practice

Write-by-yourself Java Virtual Machine, the author uses go language to implement a simple JVM, although it does not fully implement all the functions of JVM, but for some people who are slightly interested in JVM, readability is still very high. The author's explanation is very detailed, each process is divided into a chapter, part of which is to explain how to parse Class files.

This book is not very thick, and it will be finished soon. After reading it, we will have a good harvest. But I always feel shallow on paper and know nothing about it, so I try to parse the Class file myself. go language is excellent, but after all, it is not proficient, especially not accustomed to its type after the variable grammar, or honest and practical java bar.

Project address: https://github.com/HalfStackDeveloper/ClassReader

Class file

1. What is a Class file?
2. Basic structure

I can't read this paragraph clearly in the original text. Copy it.

Is it confused, but the basic format of class file is given in the java virtual machine specification, as long as it is parsed according to this format:

ClassFile {
       u4 magic;
       u2 minor_version;
       u2 major_version;
       u2 constant_pool_count;
       cp_info constant_pool[constant_pool_count-1];
       u2 access_flags;
       u2 this_class;
       u2 super_class;
       u2 interfaces_count;
       u2 interfaces[interfaces_count];
       u2 fields_count;
       field_info fields[fields_count];
       u2 methods_count;
      method_info methods[methods_count];
       u2 attributes_count;
       attribute_info attributes[attributes_count];
}
3. Structure of class file
4. Analysis
Field type

The original code segment is not clear:

public class U1 {
    public static short read(InputStream inputStream) {
        byte[] bytes = new byte[1];
        try {
            inputStream.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        short value = (short) (bytes[0] & 0xFF);
        return value;
    }
}
 
public class U2 {
    public static int read(InputStream inputStream) {
        byte[] bytes = new byte[2];
        try {
            inputStream.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        int num = 0;
        for (int i= 0; i < bytes.length; i++) {
            num <<= 8;
            num |= (bytes[i] & 0xff);
        }
        return num;
    }
}                                                                                                                                                                                   
 
public class U4 {
    public static long read(InputStream inputStream) {
        byte[] bytes = new byte[4];
        try {
            inputStream.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        long num = 0;
        for (int i= 0; i < bytes.length; i++) {
            num <<= 8;
            num |= (bytes[i] & 0xff);
        }
        return num;
    }
}
constant pool

First, read basic information such as magic numbers:

FileInputStream inputStream = new FileInputStream(file);
ClassFile classFile = new ClassFile();
classFile.magic = U4.read(inputStream);
classFile.minorVersion = U2.read(inputStream);
classFile.majorVersion = U2.read(inputStream);

The java virtual machine specification gives the format of each item in the constant pool:

cp_info {
    u1 tag;
    u1 info[]; 
}

Read the size of the constant pool and initialize the constant pool:

// Analytic constant pool
int constant_pool_count = U2.read(inputStream);
ConstantPool constantPool = new ConstantPool(constant_pool_count);
constantPool.read(inputStream);

Next, each item is read one by one and stored in the array cpInfo. It should be noted that the cpInfo [] subscript starts from 1, 0 is invalid, and the true constant pool size is constant_pool_count-1.

public class ConstantPool {
    public int constant_pool_count;
    public ConstantInfo[] cpInfo;
 
    public ConstantPool(int count) {
        constant_pool_count = count;
        cpInfo = new ConstantInfo[constant_pool_count];
    }
 
    public void read(InputStream inputStream) {
        for (int i = 1; i < constant_pool_count; i++) {
            short tag = U1.read(inputStream);
            ConstantInfo constantInfo = ConstantInfo.getConstantInfo(tag);
            constantInfo.read(inputStream);
            cpInfo[i] = constantInfo;
            if (tag == ConstantInfo.CONSTANT_Double || tag == ConstantInfo.CONSTANT_Long) {
                i++;
            }
        }
    }
}

Let's first look at the CONSTANT_Utf8 format, which stores UTF-8 encoded strings:

CONSTANT_Utf8_info { 
    u1 tag;
    u2 length;
    u1 bytes[length]; 
}

So how do I read this item?

public class ConstantUtf8 extends ConstantInfo {
    public String value;
 
    @Override
    public void read(InputStream inputStream) {
        int length = U2.read(inputStream);
        byte[] bytes = new byte[length];
        try {
            inputStream.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            value = readUtf8(bytes);
        } catch (UTFDataFormatException e) {
            e.printStackTrace();
        }
    }
 
    private String readUtf8(byte[] bytearr) throws UTFDataFormatException {
        //copy from java.io.DataInputStream.readUTF()
    }
}

Simply read the byte array length of this item first, then call readUtf8() to convert the byte array into a String string.

Let's look at the CONSTANT_Class item, which stores symbolic references to classes or interfaces:

CONSTANT_Class_info {
    u1 tag;
    u2 name_index;
}

Note that the name_index here is not a direct string, but points to the name_index item of the cpInfo array in the constant pool, and that cpInfo[name_index] must be in CONSTANT_Utf8 format.

public class ConstantClass extends ConstantInfo {
    public int nameIndex;
 
    @Override
    public void read(InputStream inputStream) {
        nameIndex = U2.read(inputStream);
    }
}

After the constant pool is parsed, it can be used for later data. For example, this_class in ClassFile points to an item in the constant pool format CONSTANT_Class, so we can read out the class name:

int classIndex = U2.read(inputStream);
ConstantClass clazz = (ConstantClass) constantPool.cpInfo[classIndex];
ConstantUtf8 className = (ConstantUtf8) constantPool.cpInfo[clazz.nameIndex];
classFile.className = className.value;
System.out.print("classname:" + classFile.className + "\n");
Bytecode instruction

method_info in ClassFile is formatted as follows:

method_info {
    u2 access_flags;		// Access Logo
    u2 name_index;			// Method Name Index
    u2 descriptor_index;	// Method Descriptor Index
    u2 attributes_count;	
    attribute_info attributes[attributes_count];	// Attribute array
}

The general format of attributes is:

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}

The format of the Code attribute is as follows:

Code_attribute {
    u2 attribute_name_index; u4 attribute_length;
    u2 max_stack;
    u2 max_locals;
    u4 code_length;
    u1 code[code_length];
    u2 exception_table_length; 
    {
        u2 start_pc;
        u2 end_pc;
        u2 handler_pc;
        u2 catch_type;
    } exception_table[exception_table_length];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

Next we can parse the bytecode:

for (int j = 0; j < methodInfo.attributesCount; j++) {
    if (methodInfo.attributes[j] instanceof CodeAttribute) {
        CodeAttribute codeAttribute = (CodeAttribute) methodInfo.attributes[j];
        for (int m = 0; m < codeAttribute.codeLength; m++) {
            short code = codeAttribute.code[m];
            System.out.print(InstructionTable.getInstruction(code) + "\n");
        }
    }
}

Topics: jvm Java Attribute Go