所谓的jvm调优:
1、根据需求进行jvm规划和预调优
2、优化jvm的运行环境
3、解决jvm运行过程中出现的各种问题
一般来讲我们处理的都是第三种情况的居多。
调优,从规划开始
调优从业务场景开始,没有业务场景的调优都是无意义的。
要测试并且能看到结果,否则调优也是无意义的。
具体步骤:
1、熟悉业务场景(没有最好的垃圾回收器,只有最合适的垃圾回收器)。
响应时间优先还是吞吐量优先?
2、选择垃圾回收器的组合
3、计算内存需求(根据经验比如8G、16G)
4、设定对象年代大小
5、设置日志参数
-Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause(参数说明:指定生成5个jvm日志文件,每个文件20M,如果日志文件都满了则干掉最早的一个文件,循环使用这5个文件;PrintGC。。。是打印GC的一些详细信息的意思)
6、观察运行情况
7、如果技术调优难就业务调优
系统卡顿排查一般思路和步骤
1、一般是运维团队首先收到报警信息(CPU高或 Memory高)
2、top命令观察到问题:内存不断增长 CPU占用率居高不下
3、top -Hp [pid] 观察进程中的线程,哪个线程CPU和内存占比高
3、jps 显示所有的java进程
jstack [进程pid]定位线程状况,可以看到所有线程的详细信息
先top 找到进程pid 123,在top -Hp pid 123 就显示该进程的所有线程了;让后把指定的线程pid 456转换为16进制; printf ‘%x\n’ pid 456 得到线程号的16进制表示比如得到4455,在前面加0x4455就是16进制了;然后jstack 123|grep -C20 0x4455 就能查看指定线程的栈信息了:
重点关注:WAITING 和BLOCKED
例如:
waiting on <0x0000000088ca3310> (a java.lang.Object)
假如有一个进程中100个线程,很多线程都在waiting on <xx> ,一定要找到是哪个线程持有这把锁, 怎么找?搜索jstack [进程pid] 的dump信息(jstack 4455 >/home/tmp/666.txt),比如找<0x0000000088ca3310> ,看哪个线程持有这把锁,一般这个线程还是RUNNABLE的状态;
4、jstat命令的使用
jstat -gc 动态观察gc情况 / 阅读GC日志发现频繁GC / arthas观察 / jconsole/jvisualVM/ Jprofiler(最好用但是要钱);( jconsole/jvisualVM是jdk自带的), jstat -gc 4655 500 : 每个500个毫秒打印GC的情况。
5、jmap - histo 4655 | head -20,查找有多少对象产生,系统也有稍微的影响
6、jmap -dump:format=b,file=xxx pid :但是会系统卡顿;
线上系统,内存特别大,jmap执行期间会对进程产生很大影响,甚至卡顿(电商不适合)
6.1:设定了参数-XX:+HeapDumpOnOutOfMemoryError,OOM的时候会自动产生堆转储文件
6.2:很多服务器(高可用),隔离这台服务器对其他服务器不影响,就可以 jmap -dump:format=b,file=xxx pid
6.3:arthas在线定位(一般小点儿公司用不到)
7、设定好程序的启动jvm参数,内存溢出的时候自动生成dump文件
java -Xms20M -Xmx20M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError xxxApp.java:这样就不需要你手动去生成dump文件了;
8、使用MAT / jhat /jvisualvm 进行dump文件分析,找到代码问题 修复即可。