JVM基础
  QNyb8JwuOaZo 2023年11月19日 67 0

从回收内存的角度看:Java 堆,由年轻代和年老代组成,分别占据 1/3 和 2/3;而年轻代又分为三部分,Eden、From Survivor、To Survivor,占据比例为 8:1:1,可调。

欢迎参观我的博客,一个Vue 与 SpringBoot结合的产物:https://poetize.cn

Java堆

从回收内存的角度看

  • Java 堆,由年轻代和年老代组成,分别占据 1/3 和 2/3。
  • 而年轻代又分为三部分,Eden、From Survivor、To Survivor,占据比例为 8:1:1,可调。

对象的创建

  • 类加载
  • 内存分配:1,指针碰撞(复制算法/标记-整理算法);2,空闲列表(标记-清除算法)
  • 初始化零值
  • 设置对象头
  • init方法

类加载过程

  • 加载:通过全限定类名加载类型数据到元空间,并在堆中生成一个代表这个类的Class对象,作为访问类型数据的外部接口。
  • 验证
  • 准备:给静态变量分配内存并设置类变量初始值的阶段。
  • 解析符号引用转为直接引用
  • 初始化:为静态变量赋代码编写的值

对象的回收

可达性算法

  • 静态变量,常量
  • 执行上下文(方法栈帧中局部对象引用)

垃圾收集器

新生代

  • Serial:复制,单线程,STW
  • ParNew:复制:多线程,STW
  • Parallel Scavenge:复制,多线程,STW,吞吐量优先收集器
  • G1

老年代

  • Serial Old:标记整理,单线程,STW
  • Parallel Old:标记整理,多线程,STW,吞吐量优先收集器
  • CMS:标记清除,并发低停顿内存碎片较多依赖CPU资源浮动垃圾
  • 初始标记:单线程,STW
  • 并发标记
  • 重新标记:多线程,STW
  • 并发清除
  • G1

CMS与G1

CMS会导致碎片化,大对象会频繁触发FullGC,FullGC意味着完全的STW,应用线程彻底停止,直到完成对堆的清理。堆越大FullGC停顿的时间就越长。

CMS垃圾回收器不能满足性能需求,而G1相比CMS有更清晰的优势:

  1. CMS没有采用复制算法,所以它不能压缩,最终导致内存碎片化问题。而G1采用了复制算法,它通过把对象从若干个Region拷贝到新的Region过程中,执行了压缩处理。
  2. CMS必须扫描整个堆来确认存活对象,所以,长时间停顿是非常常见的。而G1的停顿时间取决于收集的Region集合数量,而不是整个堆的大小,所以相比起CMS,长时间停顿要少很多,可控很多。

选择合适的垃圾回收器

  • CPU单核,那么毫无疑问Serial 垃圾收集器是你唯一的选择。
  • CPU多核,关注吞吐量 ,那么选择PS+PO组合。
  • CPU多核,关注用户停顿时间,JDK版本1.6或者1.7,那么选择CMS。
  • CPU多核,关注用户停顿时间,JDK1.8及以上,JVM可用内存6G以上,那么选择G1。

JVM 调优

1. 网站流量暴增后反应很慢

  1. 推测:垃圾收集导致业务线程停顿
  2. 定位:jstat -gc发现GC频率过高
  3. 解决:加大内存
  4. 第二个问题:加大内存后单次卡顿变长
  5. 解决:JDK1.8默认垃圾收集器Parallel Scavenge + Parallel Old,增大内存后停顿时间就变长了。可以使用CMS,并设置了一个预期的停顿时间。

2. OOM

-XX:+HeapDumpOnOutOfMemoryError参数获得堆内存的dump文件。

3. 内存飙高

1、先观察垃圾回收的情况

  • jstat -gc PID 1000查看GC次数,时间等信息,每隔一秒打印一次。
  • jmap -histo PID | head -20查看堆内存占用空间最大的前20个对象类型,可初步查看是哪个对象占用了内存。

如果每次GC次数频繁,而且每次回收的内存空间也正常,那说明是因为对象创建速度快导致内存一直占用很高;
如果每次回收的内存非常少,那么很可能是因为内存泄露导致内存一直无法被回收。

2、导出堆内存文件快照

  • jmap -dump:live,format=b,file=/home/myheapdump.hprof PIDdump堆内存信息到文件。

4. 频繁Full GC

通过jstat命令发现系统每次Young GC后大约有10%的存活对象进入老年代。

原来是因为Survivor区空间设置过小,每次Young GC后存活对象在Survivor区域放不下,提前进入老年代。

通过调大Survivor区,使得Survivor区可以容纳Young GC后存活对象,对象在Survivor区经历多次Young GC达到年龄阈值才进入老年代。



【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月19日 0

暂无评论

推荐阅读
QNyb8JwuOaZo