0
点赞
收藏
分享

微信扫一扫

JVM相关知识总结

花姐的职场人生 2022-03-10 阅读 32

JVM内存模型

在这里插入图片描述
GC如何判断对象可以被回收
① 引用计数法(淘汰)存在循环依赖不能被回收问题
② 可达性分析算法(根引用)
GCroot有哪些?
虚拟机栈中的引用 对象
方法区中静态属性引用对象
方法区中常量引用对象
本地方法栈中的引用对象
不同类型的引用类型
强引用 new 有强引用不回收
软引用 SR内存使用达到最大值时回收
弱引用 WR每次GC时回收
虚引用 PR一次性,堆外内存,销毁时发信号

什么情况下需要进行调优?
吞吐量 低延迟
① Heap内存(老年代)持续上涨达到最大值
② FullGC次数频繁
③ GC停顿过长,超过1秒
④ 出现OutOfMemory
⑤ 应用中本地缓存占用大量内存空间
⑥ 应用CPU占用居高不下
PS/PO 提高吞吐量
CMS/G1 提高响应时间
Xms Xmx Xss
工具
jconsole
top 查看cpu找到线程id
top -Hp
查看dump文件
jstack命令查看调用栈的信息
jstat监控GC情况

方法区的垃圾回收主要有两种,分别是对废弃常量的回收和对无用类的回收。
当一个常量对象不再任何地方被引用的时候,则被标记为废弃常量,这个常量可以被回收。
方法区中的类需要同时满足以下三个条件才能被标记为无用的类:
1.Java堆中不存在该类的任何实例对象;
2.加载该类的类加载器已经被回收;
3.该类对应的java.lang.Class对象不在任何地方被引用,且无法在任何地方通过反射访问该类的方法。
当满足上述三个条件的类才可以被回收,但是并不是一定会被回收,需要参数进行控制,例如HotSpot虚拟机提供了-Xnoclassgc参数进行控制是否回收。

内存溢出的几种情况?
① OOM-Javaheap space 堆栈溢出,代码无误的情况下,调整Xmx Xms
② OOM-PermGen 持久代元空间溢出,只有1.7以前会有,1.8以后元空间放在堆外内存
③ OOM-Direct buffer memory 最大缓冲内存,考虑优化-XX:MaxDirectMemorySize参数
④ StackOverflowError 栈溢出,可能递归太深,通过Xss值设置
⑤ OOM unable to create native thread 操作系统内存不够用
⑥ OOM request{}byte for out of swap 操作系统地址空间不够用

JVM有哪些垃圾回收器?

JVM调优实战

step1
top 命令查看线程cup和内存的使用率过高的线程pid 5511
在这里插入图片描述

step2
查询当前java进程详情,利用 jinfo pid 5511
在这里插入图片描述
step3
查看当前gc情况: jstat gcacuse 5511
在这里插入图片描述

发现新生代频繁的进行gc操【YGC:gc 次数, YGCT: gc时间】,老年的几乎没有gc【FGC:full gc次数,FGCT :full gc时间】,可能原因是新生代的设计过小,导致新生代频繁gc
step4
查看当前jvm 内存分配: jmap -heap 5511
在这里插入图片描述
从JVM的分配可以看出,新生代分配:capacity = 628162560 (599.0625MB),Eden Space:capacity = 558432256 (532.5625MB),老年代分配:capacity = 5744558080 (5478.4375MB)。从数据分析出,新生代设计过小,导致新生代频繁gc。其次,新生代设计过小,导致大对象无法分配,直接分配到老年代。导致老年代空间占用过大,从而占用整个系统内存空间。可能导致其他服务内存不足。

step5
线上手动GC,查看GC后的JVM详情信息 jstat -gc 5511 1000
在这里插入图片描述
手动强制Full gc 以后发现,内存并没有被释放,说明当前系统可能存在内存泄漏,导致对象不能被清理释放【OC:老年代空间,OU :老年代使用空间(KB)】。
存在内存泄漏,主要是当前的对象引用没有被释放导致,比如僵尸线程的存在。说明当前系统可能存在大量的僵尸线程。进而进行进一步的排查。
step6
查看当前系统线程情况:jstack。可以看到当前线程的详细情况 jstack 5511 | head -50
step7
查看当前系统的线程总数:jstack 5511 | wc -l
在这里插入图片描述
可以分析出,当前系统对外建立了大量的连接,而且连接没有释放,导致系统开启的线程数过多。通过分析连接最多的ip,定位到出现问题的节点
从前面的一系列的分析,可以发现,系统底层存在大量的线程,导致引用没法释放。通过对java的栈信息分析发现存在大量的ElasticSearch连接线程,导致JVM Full Gc 没法释放资源。
step8
加载当前的堆信息:jmap -dump:live,format=b,file=dump.hprof 5511
通过 Eclipse IDE MAT 插件进行堆分析
Java堆分析:
Eclipse 导入堆信息
查看当前堆内存泄漏情况
查看当前堆中占用最大的对象
通过对堆的对象分析,可以发现,当前系统中大量存在连接池对象,从而定位到问题所在,连接池出现了泄漏。导致系统大量创建连接池,而没有释放。出现了内存泄漏
通过堆信息分析,找到了问题所在,修改可能出现问题的代码,做到了jvm的全面诊断。

JVM调优实战总结

top 查看占用cpu和内存过高的 pid
jinfo pid 5511 查看该pid的进程详情
jstat gcacuse 5511 查看该进程的垃圾回收情况(YGC FGC)次数过多的需要增大
**jmap -heap ** 5511 查看内存分配情况
jstat -gc 5511 1000 手动GC,查看空间释放情况,是否存在内存泄漏(僵尸线程)
jstack 5511 | wc -l 可以查看开启的线程数
netstat 可以查看对外建立的连接数
jmap -dump:live,format=b,file=dump.hprof 5511 生成dump文件,分析dump文件,查看占用最多的对象,修改针对的代码

何时会产生内存泄漏?

① 静态集合类,静态的生命周期与应用程序一样,集合中所装的元素不会被释放
② 各种连接,未正常的close(),导致连接没有被释放
③ 单例模式下,单例对象所引用的对象有可能导致内存泄漏

举报

相关推荐

JVM相关知识

IP相关知识总结

缓存相关知识总结

JVM层面的对象相关知识

jvm的相关知识点

JVM 相关知识点记录

JVM的小知识总结

0 条评论