当前位置:网站首页>VM in-depth learning (XXV) -class file overview

VM in-depth learning (XXV) -class file overview

2022-07-05 02:54:00 zhang. yao

1. summary

The bytecode file is Java Virtual machine cross platform / The foundation of cross language .
Java Virtual machines are only bound to bytecode files , As for whether the source code of bytecode file is Java Coding is not JVM Consider the problem , This is also JVM The power of .

Bytecode generation is generated by the front-end compiler , The front-end compiler can be a compiler for multiple languages , Compile the source code to conform to JVM canonical class file , Leave it to JVM Explain to perform .
With Java For example ,jdk Can compile java Source compiler , We can use javac Come and take one java The source code file is compiled as class file .

And by right of class Detailed understanding of documents , We can see some details that cannot be expressed in the source code , How does the compiler optimize the compilation of source code .

Bytecode files are binary files .
Bytecode files are opcode and Operands form . for example bipush 20 The operation code is in front ,20 It's the operands , Operands may not

2. Front end compiler

2.1 javac

javac Is a front-end compiler , It is also the compiler we use most , Currently in idea The default compiler in is javac
javac Is a full compiler , It doesn't matter java How much has the source code changed , Full compilation .
image.png

2.2 ECJ

Eclipse Provides a difference from javac Compiler for , It's called ECJ(Eclipse Compiler For Java), Belong to Eclipse Plug in for , He is an incremental compiler , So it's faster than javac fast , And the quality is not much worse

2.3 AJC

AspectJ Compiler It can be used as idea A plug-in with javac In combination with , Improve compilation efficiency

3. Learn the advantages of looking at bytecode

Check the bytecode of several examples , Understand the benefits of bytecode .

3.1 Patients with a

Let's start with an example :

public class ClassTest {
    
    public static void main(String[] args) {
    
        Integer i1 = 10;
        int i2 = 10;
        System.out.println(i1 == i2);
    }
}

The result is true, Why? ?
Let's look at bytecode , That's pretty clear :
image.png

Through the second line, we can see i1 The definition of is essentially a Integer.valueOf Method , Let's enter this method and take a look :

public static Integer valueOf(int i) {
    
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
//  Get into cache Method   Static inner class 
private static class IntegerCache {
    
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
    
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
    
                try {
    
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
    
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {
    }
    }

You can see it's a IntegerCache After getting the value (int by 10 No more than low Value -128 high Value 127); IntegerCache Yes -128 To 127 this 256 A number is cached , So the number obtained 10 It's essentially int 10
So the output is true

3.2 Example 2

String splicing is from jvm Look at the string

package com.zy.study15;

/** * @Author: Zy * @Date: 2022/2/7 15:45 *  Bytecode view string splicing  */
public class ClassTest {
    
    public static void main(String[] args) {
    
        //  It's actually StringBuilder The joining together of   What is generated is a new String object 
        String helloWorld = new String("hello") + new String("world");
        //  String constant pool 
        String helloWorld1 = "helloworld";

        //  It's not equal  false
        System.out.println(helloWorld == helloWorld1);

        //  It is also a newly created object 
        String helloworld2 = new String("helloworld");
        //  It's not equal  false
        System.out.println(helloWorld1 == helloworld2);

    }
}

The bytecode is as follows :

 0 new #2 <java/lang/StringBuilder>
 3 dup
 4 invokespecial #3 <java/lang/StringBuilder.<init> : ()V>
 7 new #4 <java/lang/String>
10 dup
11 ldc #5 <hello>
13 invokespecial #6 <java/lang/String.<init> : (Ljava/lang/String;)V>
16 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
19 new #4 <java/lang/String>
22 dup
23 ldc #8 <world>
25 invokespecial #6 <java/lang/String.<init> : (Ljava/lang/String;)V>
28 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
31 invokevirtual #9 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
34 astore_1
35 ldc #10 <helloworld>
37 astore_2
38 getstatic #11 <java/lang/System.out : Ljava/io/PrintStream;>
41 aload_1
42 aload_2
43 if_acmpne 50 (+7)
46 iconst_1
47 goto 51 (+4)
50 iconst_0
51 invokevirtual #12 <java/io/PrintStream.println : (Z)V>
54 new #4 <java/lang/String>
57 dup
58 ldc #10 <helloworld>
60 invokespecial #6 <java/lang/String.<init> : (Ljava/lang/String;)V>
63 astore_3
64 getstatic #11 <java/lang/System.out : Ljava/io/PrintStream;>
67 aload_2
68 aload_3
69 if_acmpne 76 (+7)
72 iconst_1
73 goto 77 (+4)
76 iconst_0
77 invokevirtual #12 <java/io/PrintStream.println : (Z)V>
80 return

From the bytecode, you can see many String How to add objects , Created StringBuilder Object to carry out append operation , Last call toString Method

3.3 Example 3

package com.zy.study15;

/** * @Author: Zy * @Date: 2022/2/9 18:44 *  From the perspective of bytecode, parent and child classes  */
public class ClassTest2 {
    
    static class Father{
    
        int num = 0;
        void print(){
    
            System.out.println("Father Print ,num The value of is "+num);
        }
        Father(){
    
            print();
            num = 20;
        }
    }

    static class Son extends Father{
    
        int num = 100;
        @Override
        void print(){
    
            System.out.println("Son Print ,num The value of is "+num);
        }
        Son(){
    
            print();
            num = 200;
        }
    }

    public static void main(String[] args) {
    
        //  polymorphic   There are prints in the constructors of parent and child classes , Then print num What is the result , Why? 
        Father father = new Son();
        System.out.println(father.num);
    }
}

Print the results
image.png
To explain this result, just look at the bytecode
new Son() Essentially, it calls the constructor , So let's look at the constructor method

3.3.1 Father class init Bytecode

 0 aload_0 this object 
 1 invokespecial #10 <java/lang/Object.<init> : ()V>  Parent class Object Construction method of 
 4 aload_0
 5 iconst_0  Constant 0  That is to say num The default value of 
 6 putfield #6 <com/zy/study15/ClassTest2$Father.num : I>  to num Assign default initial value 0
 9 aload_0 
10 invokevirtual #11 <com/zy/study15/ClassTest2$Father.print : ()V>  call Print Method , Print num
13 aload_0
14 bipush 20  In the construction method num assignment 20, Here is the extraction constant 20
16 putfield #6 <com/zy/study15/ClassTest2$Father.num : I>  to num assignment 20
19 return

3.3.2 Son class init Bytecode

 0 aload_0
 1 invokespecial #10 <com/zy/study15/Father.<init> : ()V>  Empathy , Parent class Father Construction method of 
 4 aload_0
 5 bipush 100  Take out 100 
 7 putfield #6 <com/zy/study15/Son.num : I>  to num Fu 100
10 aload_0
11 invokevirtual #11 <com/zy/study15/Son.print : ()V> Print Printing method , Print num
14 aload_0
15 sipush 200  Fetch constant 200
18 putfield #6 <com/zy/study15/Son.num : I>  to num assignment 200
21 return

Explain :

  1. new Son() Will call first Son Construction method of class , The specific implementation process can be seen in the above Son Class init Bytecode
  2. from Son Of init During the execution of the construction method, you can see , Call the parent class on the second line Father Construction method of .
  3. Call this time Father Construction method of
  4. You can see In print num When , Only to num Given the initial value 0, So the value printed for the first time is 0
  5. And because of polymorphism ,Print Method subclassed Son rewrite , So the printed content is Son Print , instead of Father Print
  6. After executing the constructor of the parent class , Continue to back Son Class init Method
  7. You can see Print num Give to before num Fu 100, So print num The value of is 100
  8. Later num Fu 200, So get Son Of num The value is 200 了 .
  9. The output of the last line is 20, This is because what we get is Father Of num value , instead of Son Of num Value .

3.3 summary

Through bytecode, you can see the execution process of some code that is not easy to understand .

4. How to view bytecode files

4.1 Third party software

install Binary Viewer Tools , You can open bytecode files
**Binary Viewer Installation package **https://www.aliyundrive.com/s/5HCJfAFQoxf Extraction code 0eo6

image.png
perhaps Notepad++ plug-in unit Hex-Editor
Install directly in the plug-in market ( If there is a problem in the plug-in market , Try installing the latest version notepad++)
image.png
image.png

4.2 jdk Bring their own javap

#  take class The decompiled contents of the file are output to the current directory 
javap -v ClassTest.class > ClassTestOut.java

image.png
image.png

4.3 idea plug-in unit jclasslib

idea Plug in market installation jclasslib that will do
The effect is as follows :
image.png

原网站

版权声明
本文为[zhang. yao]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202140841373082.html