仅以此记录学习笔记等!
JVM调优
常见的调优指令
jps
查看应用程序对应的进程id
jmap
内存
查看内存信息,实例个数,占用内存的大小等
jmap -histo 27500(可添加 > ./testLog.txt 生成txt到当前目录下)
- num:序号
- instances:实例数量
- bytes:占用空间大小
- class name:类名称,[C is a char[],[S is a short[],[I is a int[],[B is a byte[],[[I is a int[][
堆
查看堆信息:jmap -heap 27500
堆快照dump:jmap -dump:format=b,file=xxx.hprof 27500
设置堆内存溢出自动dump:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./(生成文件路径)
jstack
得到运行java程序的java stack和native stack的信息
格式:
jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP
场景:
1死锁,Deadlock
2等待资源,Waiting on condition
• 等待获取监视器,Waiting on monitor entry
3阻塞,Blocked(重点关注)
• 执行中,Runnable
• 暂停,Suspended
• 对象等待中,Object.wait() 或 TIMED_WAITING
• 停止,Parked
查看程序cpu及内存使用情况
top -p <pid>
执行 jstack 19663|grep -A 10 4cd0,得到线程堆栈信息中 4cd0 这个线程所在行的后面10行,从堆栈中可以发现导致cpu飙高的调用方法
jinfo
查看jvm的参数:jinfo -flags <pid>
查看java程序的参数:jinfo -sysprops <pid>
jstat
以查看堆内存各部分的使用量,以及加载类的数量。(注意:使用的jdk版本是jdk8 )
命令格式: jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]
常用指令:
查看程序内存使用及GC压力整理情况:jstat -gc pid
查看堆内存统计:jstat -gccapacity pid
查看新生代内存统计:jstat -gcnewcapacity pid
查看新生代垃圾回收统计:jstat -gcnew pid
查看老年代内存统计:jstat -gcoldcapacity pid
查看老年代垃圾回收统计:jstat -gcold pid
查看元数据空间统计:jstat -gcmetacapacity pid
jvisualvm
1导入dump文件分析堆信息
2线程dump,查看当前线程运行信息
优化思路
先给自己的系统设置一些初始性的 JVM参数,比如堆内存大小,年轻代大小,Eden和Survivor的比例,老年代的大小,大对象的阈值,大龄对象进入老年代的阈值等。
1.年轻代对象增长的速率
jstat -gc pid 1000 10(每隔1s执行1次,共执行10次)观察EU区的使用,来估算每秒Eden区大概有多少新增的对象。当系统负荷不高时,可以将执行时间调大到1分钟甚至10分钟来观察。
2.young gc触发的频率和单次耗时时间
公式:触发频率=YGCT/YGC(jstat命令可查看,YGCT young gc总耗时单位s,YGC young gc次数)
3.每次young gc后有多少对象是存活的且进入老年代
从第二点中知道young gc频率,如果是10分钟一次那么 jstat -gc pid 600000 10,就可以通过该指令查看gc中,每次Eden区、Survivor、老年代区的使用及变化情况。众所周知,每次gc后,eden区存活对象减少,Survivor、老年代都有可能增长,这些增长的对象就是每次young gc后存活的对象,可以看出每次young gc有多少存活的对象是进入到老年代中的,推算出老年代的增长速率。
4.Full GC的触发频率和单次耗时时间
公式:触发频率=FGCT/FGC(FGCT full gc总耗时单位s,FGC full gc次数)
思路:基本看来就是
1尽量让每次young gc后的存活对象小于Survivor区域的50%,将存活对象留在新生代中,尽量别让对象进入老年代中。
2尽量减少full gc的频率,避免频繁full gc对jvm性能的影响。
3新生代或者老年代的增长过快之类的,回顾其内存分配时注意的一些点。