引言:

什么是jvm

程序运行时,JVM 会对字节码文件进行逐行解释,翻译成机器码指令,并交给对应的操作系统去执行。

jvm的特性

①、JVM 可以自动管理内存,通过垃圾回收器回收不再使用的对象并释放内存空间。

②、JVM 包含一个即时编译器 JIT,它可以在运行时将热点代码缓存到 codeCache 中,下次执行的时候不用再一行一行的解释,而是直接执行缓存后的机器码,执行效率会大幅提高。

jvm的架构

① 类加载器:负责从文件系统、网络或其他来源加载 Class 文件,将 Class 文件中的二进制数据读入到内存当中。

② 运行时数据区:JVM 在执行 Java 程序时,需要在内存中分配空间来处理各种数据,这些内存区域按照 Java 虚拟机规范可以划分为方法区、堆、虚拟机栈、程序计数器和本地方法栈。

③ 执行引擎:也是 JVM 的心脏,负责执行字节码。它包括一个虚拟处理器、即时编译器 JIT 和垃圾回收器。

内存管理

java字节码文件:

image-20250904171746785

jvm运行时数据区:

image-20250904085801572

有什么?

程序计数器:每个线程私有,记录当前程序执行的位置

Java虚拟机栈:主要存储的是局部变量和对象的引用;每个方法会产生一个栈帧,每个栈帧包括局部变量区(在编译的时候就确定),操作数栈和方法返回地址,动态链接(可能存在多态的方法在编译时由于符号引用相同无法通过静态链接来转换成地址引用,所以需要在运行的时候通过查找表来确定实际的方法来进行需要动态链接)

本地方法栈:本地方法用到的栈

Java堆:主要存储的是对象的实例

方法区:存储类的结构信息括类的定义、方法的定义、字段的定义以及字节码指令,运行时常量池(就是把.class文件中的常量池进行链接后的状态)

方法区中的方法的执行过程:

img

常见问题:

引用类型有哪些?有什么区别,弱引用了解吗?

强引用:永远不会被GC

软引用:当内存溢出之后被回收

弱引用:每次GC都会被回收

虚引用:每次GC都会被回收

内存泄漏和内存溢出:

内存泄露:程序运行过程中不再使用的对象仍然被引用,而无法被垃圾回收器回收(ThreadLocal的内存泄漏问题)

内存溢出:申请内存时候,无法找到足够的内存

类加载:

类加载器

有哪些?

启动类加载器

扩展类加载器

应用程序加载器

用户自定义类加载器

关系链:

这条链在构造器里就写死了,不会因为后续你改写了加载策略而变化。

扩展作用:

类加载还可实现class文件加密,之后再到自定义类加载器中解密

双亲委派模型,它的作用:

img

每层加载器判断自己能否加载这个请求的依据是这个class文件在目录中的位置

加载之后会留下缓存,下次发现这个类加载过就直接用了

作用:
1:通过委派机制避免了不同类加载器加载相同类的情况,防止同一个类出现多份定义
2:防止了核心类被假冒,核心类通过双亲委派机制被启动类加载器加载,启动类加载器访问的目录普通用户是无权将文件添加进来的

打破双亲委派:自己实现加载不了再找父亲,不是直接断开了

经典案例:

tomcat这样的热部署框架:因为一个tomcat上可以有多个服务,不同服务可能有重名,每个服务要有自己的自定义类加载器。

讲下java类生命周期:

类加载包括:加载,链接,初始化

img

img

垃圾回收

垃圾回收:

什么是垃圾回收?

自动管理内存的一种机制,负责自动释放不再被程序引用的对象所占的内存。

如何触发垃圾回收?

内存不足或手动请求

判断垃圾的方法有哪些?

img

gc只会对堆进行gc吗?

也会对方法区进行回收

垃圾回收算法:

垃圾回收算法有哪些?

标记-清除:标记之后直接清理,容易产生内存碎片

标记-整理:标记清理整理一下,代价太大了

复制:将内存分为2个区,把不需要删除的放到另一个区,之后把那个区全部删除,需要两倍的内存

分代:老年代和新生代采用各自的垃圾回收算法并且新生代经过几轮GC后会被送到老年代

垃圾回收器:

有哪些?

img

minorgc,majorgc,fullgc的区别?

重新标记是保障不误删,都可以允许漏删。初次标记是为了把时间更久的标记交给并发标记。

CMS:

流程:

img

G1:

流程:

img