Jvm调优主要三方面:
1.自己的代码是否存在缺陷
2.垃圾回收器的选择
3.jvm参数的调整
什么是垃圾
没有任何引用指向的对象或者一堆对象(多个对象循环引用)
找到垃圾:
1.referece count 引用计数(无法找到循环引用),计算被引用的个数,容易造成内存泄漏
2.jvm真正使用的事跟可达算法root searching,跟对象包括下图四种。(可以简单理解于main里的)
回收垃圾:(如下三种)
标记清除:标记出垃圾,清理(位置不连续,碎片太多)
拷贝算法:内存分两部分,把不是垃圾的复制到下面,再把上面是垃圾的清理掉,然后从下面部分开始用,循环(缺点:浪费空间,需要两倍的内存,用于拷贝)
标记压缩:将存活对象复制到垃圾对象空间处(效率偏低,需要移动,任何一块挪动都要进行线程同步)
实际是看垃圾回收器是使用哪种算法.
新生代,老年代
1.7还有永久代
1.8支持 g1(逻辑分代,物理部分代)
Jmap (会造成卡顿,卡很长时间)
Jmap -histo id 显示类的视图,分析哪些类产生多少对象,多少内存
前20个
整个内存存在硬盘上,产生dump文件,生成环境中不能用,太大了,8个g还可以接受
远程连接
Arthas是在线的分析工具
Jvm命令 可知道使用哪种垃圾回收器
Thread
Jad(在线java反编译)
在线修改代码
1.修改tt.class
2.redefine /root/TT.class
若多台服务器,就要一台一台改,多台不推荐
Java启动日志设置
1.不推荐(会非常太大)
2.5个日志文件,不断循环,5个文件满了清一个继续写,滚动性日志(详细日志)
Allocation failure 分配不下了
System.gc()是full gc
Jstack查看线程的情况,主要用来判断死锁和死循环问题,cpu高,但无法解决oom的问题
Cpu飙高问题,死循环:
1.Jstack 8247 > 8247.txt 存文件
2.找2037的进程
3.查看下面的方法
死锁
Jstat 可以查看gc情况,不常用,太难用了
Arraylist底层是一个数组,每次扩容都会复制之前的元素到新的数组中
Linklist是双向数组
优化:
内存泄漏:
指针还在
改进:
jmap -histo:live
这个命令执行,JVM会先触发gc,然后再统计信息。
- jmap -dump
这个命令执行,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用。 - jmap -permstat
这个命令执行,JVM会去统计perm区的状况,这整个过程也会比较的耗时,并且同样也会暂停应用。 - jmap -histo:live
这个命令执行,JVM会先触发gc,然后再统计信息。
上面的这三个操作都将对应用的执行产生影响,所以建议如果不是很有必要的话,不要去执行。
另外,在排查问题的时候,对于保留现场信息的操作,可以用gcore [pid]直接保留,这个的执行速度会比jmap -dump快不少,之后可以再用jmap/jstack等从core dump文件里提取相应的信息,不过这个操作建议大家先测试下,貌似在有些jdk版本上不work。
jmap相关的只能命令都
应该拉下集群再执行。