【Java】JVM字节码分析

java,jvm · 浏览次数 : 0

小编点评

一、功能 1. 工作原理:JVM负责运行Java字节码文件,将其转换为机器码并执行。 2. 内存管理:自动分配和回收内存,实现垃圾回收机制。 3. 即时编译:通过即时编译器(JIT),在需要时将字节码转换为机器码并保存在内存中,以提高执行效率。 二、解释字节码 1. 使用工具jclasslib工具查看class字节码。 2. 分析class文件:以HelloWorld为例,其字节码文件头文件为CAFEBABE1。 3. public class HelloWorld { public static void main(String[] args) { int i = 0; int j = i+1; System.out.println(j); } } 对应的.class字节文件为: 0 iconst_0 #将常量0放入操作数栈中 1 istore_1 #将操作数栈顶的数值存储到局部变量表1的位置 2 iload_1 #将局部变量表1中的数复制到栈上 3 iconst_1 #将常量1放入操作数栈中 4 iadd #将栈中最上面两个值进行相加,存储到栈顶 5 istore_2 #从栈中取出操作数放入局部变量表中2号位置 13 return #方法结束 三、分析i++ 1. public class HelloWorld { public static void main(String[] args) { int i = 0; i = i++; System.out.println(i); } } 对应的.class字节文件为: 0 iconst_0 #将常量0放入操作数栈 1 istore_1 #将栈顶元素取出存储到局部变量表1的位置 2 iload_1 #将局部变量表1位置的操作数复制到操作栈 3 iinc 1 by 1 #将布局变量表1的位置的值加1 6 istore_1 #将栈顶元素取出存储到局部变量表1的位置 10 iload_1 #将布局变量表1位置的操作数复制到操作数栈 14 return结果输出为0 四、分析++ 1. public class HelloWorld { public static void main(String[] args) { int i = 0; i = ++i; System.out.println(i); } } 对应的.class字节文件为: 0 iconst_0 #将常量0放入操作数栈 1 istore_1 #将栈顶元素取出存储到局部变量表1的位置 2 iinc 1 by 1 #将布局变量表1的位置的值加1 5 iload_1 #将布局变量表1位置的操作数复制到操作数栈 6 istore_1 #将栈顶元素取出存储到局部变量表1的位置 10 iload_1 #将布局变量表1位置的操作数复制到操作数栈 14 return输出结果为1 } 归纳总结: - JVM负责运行Java字节码文件,并将其转换为机器码。 - 内存管理:自动分配和回收内存,包括自动垃圾回收机制。 - 即时编译器(JIT):通过即时编译技术,提高字节码的执行效率。 - 类文件结构:头部信息包含文件类型、版本号等信息,以及方法字节码等内容。 - 代码优化:JVM会识别热点代码,并将其编译成本地机器码以提高执行速度。

正文

一、功能

1、工作原理

whiteboard_exported_image (1).png

2、解释和运行

jvm本质上是运行在计算机上的程序,负责运行java字节码文件

对字节码文件中的指令,实时的解释成机器码,供计算机执行

3、内存管理

自动为对象、方法等分配内存

自动垃圾回收机制,回收不再使用的对象

4、 即时编译

在java中每次执行都需要实时解释字节码文件成机器码,导致效率较低、速度变慢。这么做的原因是因为需要跨平台,不同操作系统的java虚拟机不同,解释编译的也不一样,不同的虚拟机会转成当前操作系统的字节码。

即时编译就是为了解决这个性能问题。JVM会识别热点代码(短时间多次调用), 会主动优化并且解释成机器码 ,将这个机器码保存在内存中。下次如果调用这段热点代码会直接从内存中取出调用。这样就省略了一次解释的步骤。这样在某些情况下性能就会提升很大

二、解释字节码

使用工具jclasslib工具查看class字节码

class字节文件的头文件的前四个字节是检验文件类型用的,class字节文件的头文件为CAFEBABE

1、分析class文件

public class HelloWorld {
    public static void main(String[] args) {
        int i = 0 ;
        int j = i+1;
        System.out.println(j);
    }
}

对应的.class字节文件为

 0 iconst_0    #将常量0放入操作数栈中
 1 istore_1    #将操作数栈顶的数值存储到局部变量表1的位置
 2 iload_1     #将局部变量表1中的数复制到栈上
 3 iconst_1    #将常量1放入操作数栈中栈中
 4 iadd        #将栈中最上面两个值进行相加,存储到栈顶
 5 istore_2    #从栈中取出操作数放入局部变量表中2号位置
13 return      #方法结束

whiteboard_exported_image.png

2、分析i++

public class HelloWorld {
    public static void main(String[] args) {
        int i = 0 ;
        i = i++; 
        System.out.println(i);
    }
}
 0 iconst_0       #将常量0放入操作数栈
 1 istore_1       #将栈顶元素取出存储到局部变量表1的位置
 2 iload_1        #将局部变量表1位置的操作数复制到操作栈
 3 iinc 1 by 1    #将布局变量表1的位置的值加1
 6 istore_1       #将栈顶元素取出存储到局部变量表1的位置
10 iload_1        #将布局变量表1位置的操作数复制到操作数栈
14 return

结果输出为0

3、分析++i

public class HelloWorld {
    public static void main(String[] args) {
        int i = 0 ;
        i = ++i; 
        System.out.println(i);
    }
}
 0 iconst_0       #将常量0放入操作数栈
 1 istore_1       #将栈顶元素取出存储到局部变量表1的位置
 2 iinc 1 by 1    #将布局变量表1的位置的值加1
 5 iload_1        #将布局变量表1位置的操作数复制到操作数栈
 6 istore_1       #将栈顶元素取出存储到局部变量表1的位置
10 iload_1        #将布局变量表1位置的操作数复制到操作数栈
14 return

输出结果为1

与【Java】JVM字节码分析相似的内容: