一张图搞懂JVM
发布时间:2026/8/29 16:31:43 作者:尧图编辑部 阅读量:1,286

1.方法区线程共享存储的是常量池、静态变量(static)以及方法信息(修饰符、方法名、返回值、参数等)、类信息(类变量)等。2.堆内存线程共享堆储存的是实例对象3.虚拟机栈线程隔离储存8大基本类型 对象引用 实例方法。4.本地方法栈线程隔离储存本地接口库里调用的方法就是java里面native关键字修饰的方法去调用底层c/c语言的库首先会进入本地方法栈然后到本地方法接口。5.程序计数器线程隔离每个线程启动是都会创建一个程序计数器保存的是正在执行的jvm指令程序计数器总是指向下一条即将被执行指令的地址。生命周期与线程的生命周期保持一致。6.GC回收算法引用计数法无法解决循环引用的问题、可达性分析。7.GCRoot栈中的本地变量、方法区中的静态变量、本地方法栈中的变量、正在运行的线程。8.spring如何解决循环依赖①.Spring使用三级缓存解决大部分循环依赖问题。一级缓存存放的是已经完成初始化的Bean二级缓存存放的是早期的、还未完成初始化的Bean三级缓存存放的是ObjectFactory表示对象工厂用来创建某个对象的。②.首先实例化A同时会创建工厂对象并存放在三级缓存中。第二步在实例化A的过程中发现需要依赖B这时会走B的创建逻辑。同时也会创建B的工厂对象也存入三级缓存中。第三步B需要依赖A通过三级缓存来获取对应的工厂对象生成一个A的代理对象并存入到二级缓存中这也是三级缓存的关键所在。第四步B通过二级缓存获取到A的代理对象然后就可以正常注入了B创建成功后会存入到一级缓存中。第五步回到A的初始化此时B已经创建完成了所以可以直接注入BA创建成功后也会存入到一级缓存中。最后一步是清除二级缓存中A的代理对象。③.三级缓存并不能解决构造函数中的循环依赖问题可以通过Lazy注解懒加载来解决。JDK8 G1回收器1.堆不再固定划分年轻代老年代而是拆成大量大小相等的Region区可以动态充当Eden、Survivor、Old、Humongous(大对象区)2.回收思路优先回收垃圾最多的Region区(Garbage First)3.回收算法存活对象复制转移自动消除碎片可以设置期望停顿时间(-XX:MaxGCPauseMillis200)JDK21 ZGC(不分代24分代ZGC)1.染色指针在对象指针高位标记对象状态(未标记、已标记、重定位)不需要再对象Header存储标记2.读屏障访问对象时检查指针状态如果对象被移动返回新地址移动对象全程并发不需要STW3.几乎所有阶段并发标记、重定位(转移)、清除只有GC Roots扫描短暂STW停顿是微秒级4.优点GC停顿1ms缺点内存开销略高不分代没有新生代YGC短期大量小对象会造成回收频率升高JDK24退出分代ZGC解决也可通过实验分代ZGC设置参数解决