JVM-1

Java JVM

课程链接:https://www.bilibili.com/video/BV1r94y1b7eS/?spm_id_from=333.337.search-card.all.click&vd_source=e331db5667bdaae8e7e5c9ff63da5927

第一课:实战JVM-基础篇

初始jvm

字节码文件详解

jvm的内存区域

jvm的垃圾回收

初始jvm

java Virtual machine,java虚拟机

加载字节码.class文件,将字节码转化为机器码,机器码就可以交给计算机运行了。

  1. 解释运行
  2. 内存管理
    1. 自动为对象方法分配内存
    2. 垃圾自动回收
  3. 即时编译

java不做优化,性能是不如C和C++的

C和C++可以直接转化为机器码文件直接运行,少去了解释的步骤。

由于jvm需要实时的解释虚拟机指令,不做任何优化时,性能是不如C和C++的。

jvm的功能-及时编译:Just-In-Time(JIT)

jvm会将热点代码字节码指令解释并优化成汇编和机器码语言,关键在于他会保存在内存中,当下次还需要运行这段代码时,就去内存中加载,就省去了一次解释的步骤

常见的jvm-Java虚拟机规范

《java虚拟机规范》有Oracle指定,内容主要包含了java虚拟机在设计和实现时需要遵循的规范,只要包含class字节码文件的定义,类和接口的加载和初始化,指令集等内容。

《java虚拟机规范》是对虚拟机设计的要求,不是对java设计的要求,也就是说虚拟机可以运行其他的语言,比如Groovy,Scala生成的.class字节码文件。

常见的jvm


image-20240919091035127


总结

image-20240919091648558

字节码文件

JVM的组成

1类加载器(ClassLoader),

2运行时数据区域(JVM管理的内存),

3执行引擎(即时编译,解释器,垃圾回收等),

4本地接口(调用底层用C++写的方法)

字节码文件的组成

1)打开字节码文件:

推荐使用 Jclasslib 查看,链接:https://github.com/ingokegel/jclasslib/releases/tag/6.0.5

2)字节码文件的组成

基础信息,接口:魔数,字节码文件的java版本号,访问标识符(public final等),父类和接口

常量池:保存了字符串常量,类或接口名,字段名,主要在字节码指令中使用

字段:当前类或接口声明的字段信息

方法:当前类或接口声明的方法信息,字节码指令

属性:类的属性,比如源码的文件名,内部类的列表等

详解;

基础信息:一般消息:

Magic魔数:ca fe ba be,文件是没办法通过文件扩展名来确认文件的,软件识别类型是通过文件头几个字节识别的

image-20240919095933449

主副版本号

主版本号,jdk1.0-1.1使用了45-45.3,jdk1.2是46,在JDK1.2以后的大版本号的计算方式就是:主版本号-44,比如主版本号为52就是jdk8

副版本号:当主版本号相同是做标识用的。一般值关注主版本号

作用:判断当前的字节码文件和运行时的jdk是否兼容。

image-20240919100836874

常量池

为了避免重复的内容被重复定义,节约空间

方法

字节码中的方法区域是存放 字节码指令 的核心位置,字节码指令的内容存放在方法的Code属性中。

操作数栈(临时存放):先进后出

2)局部连量表:是一个数组实现的

常见字节码指令的作用:

iconst_0:表示把0这个常量放入操作数栈中

istore_1:表示从操作数栈中取出放入局部变量表1号的位置(剪切)

iload_1:表示从局部变量表的1号位取到操作数栈(复制)

iadd:(+操作)表示把操作数栈中最上面的两个数相加(删除原来的两个数),结果放入操作数栈最上面。

iinc 1 by 1:(++操作)表示在局部变量表1号位置增加1

例题1:int i = 0;i = i++,问最终的i的值是多少?

解答:

image-20240919134005049

中间无论加了多少次都会被覆盖!

那,++i呢

image-20240919134108199

++i和i++的 iinc和iload的顺序是相反的

image-20240919134150677

课后题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int i = 0, j = 0, k = 0;
i++;
j = j + 1;
k += 1;

问:这三个”加一“,的操作性能的高低

答:
根据分析字节码文件:
0 iconst_0
1 istore_1
2 iconst_0
3 istore_2
4 iconst_0
5 istore_3
// 0-5是数据准备

6 iinc 1 by 1
// 6是i++

9 iload_2
10 iconst_1
11 iadd
12 istore_2
// 9-12是 j = j + 1

13 iinc 3 by 1
// 13 是 k += 1
16 return

由此可见,1,3性能一样,2的性能最不好

但这种字节码层面的差异在实际运行中的性能影响通常是可以忽略不计的。现代的 JVM 会对这些常见操作进行优化,在大多数情况下,我们不需要过于关注这种细微的差异,而应更注重代码的可读性和可维护性。

玩转字节码常用工具:javap -v命令

javap是JDK自带的反编译工具,可以在控制台查看到字节码文件的内容,适合在服务器上查看字节码文件内容。

1
javap -v simpleCode.class
1
2
3
4
5
6
7
8
9
10
11
javap // 查看所有,帮助
javap -version

// 如果是jar包,需要解压出来
jar -xvf xxx.jar
// 如果是springboot项目,字节码文件就在BOOT-INF文件夹下面。

// 查看
javap -v xxx.class
// 把输出的结果保存到xxx.txt文件中
javap -v xxx.class > /opt/jvm/xxx.txt
玩转字节码常用工具:jclasslib ide插件

暂时没发现在哪里打开,看插件说明

When an editor with a Java class file is focused, invoke “View->Show Bytecode With jclasslib” from the menu

玩转字节码常用工具:阿里的arthas

插件连接: https://arthas.aliyun.com/doc

arthas 是一款线上监控诊断产品,通过全局视角实时查看应用load,内存,gc,线程的状态等信息,并能在不修改应用代码的情况下,对业务问题进行诊断,大大提升线上问题排查效率。

image-20240919171350679

可以直接下载jar包:arthas-boot.jar 使用

线上环境使用 arthas 的 dump 命令导出字节码文件再查看本地文件,还可以使用 jad 命令反编译出源代码


JVM-1
http://example.com/2024/09/19/JVM/JVM-1/
作者
JcenLeung
发布于
2024年9月19日
许可协议