欢迎访问『www.cnblogs.com/blog-ice』

自动导出堆栈信息脚本

#!/bin/bash
echo -e "------------------------------------------------begin `date +%Y-%m-%d\ %H:%M:%S`---------------------------------------"
#source /home/cfs/.bash_profile   #如果需要重新加载环境变量 可以加上
date=`date +%Y%m%d%H%M`
applction_pid=`jps -l | grep "Bootstrap" | awk '{print $1}'` 
jstacklog_name="web_jstack.log"   #日志名称
jmaplog_name="web_jmap.log"
tar_name=web_jvmlog_$date.tar.gz

jstack $applction_pid > $jstacklog_name
jmap -dump:live,format=b,file=$jmaplog_name $applction_pid

tar -zcf /home/hermes/jvm/$tar_name $jstacklog_name $jmaplog_name
rm -f $jstacklog_name && rm -f $jmaplog_name

echo -e "------------------------------------------------end `date +%\Y-%m-%d\ %H:%M:%S`---------------------------------------"

 

内存和cpu问题解决方案

一、内存:
1.导出整个jvm中的内存信息
jmap -dump:live,format=b,file=文件名.hprof pid
jmap -dump:在线对象,format=二进制格式,file=导出文件名 java进程id
或者启动参数配置
-XX:+HeapDumpOnOutOfMemoryError OOM的时候·自动生成dump文件
-XX:HeapDumpPath 导出文件路径
2.jhat -J-Xmx1024M 上述文件名
访问ip:7000
分析堆中对象的内存占用情况
3.查看内存信息
jstat -gcutil pid 打印时间间隔(毫秒) 打印次数


二、cpu
找出cpu负载高的线程
方法一、利用top
1.找出cpu最高的进程id
top -c
2.找出cpu负载高的线程id,将这个数字转换成16进制(10进制转16进制,用linux命令: printf %x 线程id)
执行top -H -p 进程id
方法二、利用ps
查进程中占用cpu高的线程
ps -mp 进程id -o THREAD,tid,time | sort -rn
将线程的id从10位转到16位,可以在下面jstack中找到对应线程


三、线程
1.看到JVM 中线程的运行状况,包括锁等待,线程是否在运行,包括死锁进程
jstack -l pid > thread.log
-l表示lock,如果出现死锁会出现deadlock信息
用记事本打开,搜索上述的16进制
排查问题从这里深入


四、常用命令
1.jps 显示所有虚拟机进程
2.jstat 监视虚拟机运行时状态信息
jstat -选项 进程id 间隔 输出次数
2.1 -class
加载class的数量|字|未加载数量|字节|加载用时
2.2 -compiler
编译数量|编译失败数量|无效数量|编译耗时|失败类型|失败方法的全限定名
*2.3 -gc 垃圾回收堆的行为统计
GC回收次数,GCT回收时间
2.4 -gccapacity 最大、最小空间
2.5 -gcutil 已使用空间占总空间的百分比
2.6 -gccause 最近两次垃圾回收事件的原因
LGCC:上一次GC原因,GCC:本次GC原因
2.7 -gcnew 统计新生代的行为
2.8 -gcnewcapacity 新生代与其相应的内存空间的统计
2.9 -gcold 统计旧生代的行为
2.10 -gcoldcapacity 统计旧生代的大小和空间
2.11 -gcpermcapacity 永生代行为统计
2.12 -printcompilation hotspot编译方法统计
3.jmap 生成heap dump文件
还可以用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM的时候·自动生成dump文件
jmap -选项 进程id
3.1 -dump:live,format=b,file=xxx.hprof 进程id 导出堆到文件
3.2 -finalizerinfo 打印等待回收对象的信息
3.3 -heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况
3.4 -histo 打印堆的对象统计,包括对象数、内存大小等等
4.jhat 分析dump文件

 

垃圾回收

垃圾回收主要集中于Java堆和方法区

一、对象存活的判断
1.引用计数
2.可达性分析:引用链
二、垃圾收集算法
1.标记-清除-----空间碎片太多
2.复制-----------内存减少一半,持续复制生存期长的对象效率降低
3.标记-压缩-----
分代选择:根据存活对象的数量选择(新生代:复制,老年代:标记清除或压缩)
三、垃圾回收器
1.Serial:稳定、高效、较长停顿、一个线程(复制+标记压缩)
-XX:+UseSerialGC
2.ParNew:Serial的多线程版本、新生代并行、老年代串行
-XX:+UseParNewGC
-XX:ParallelGCThreads限制线程数量
3.Parallel:类似UseSerialGC,自动调整停顿时间
-XX:+UseParallelGC
4.CMS(Concurrent Mark Sweep):并发收集、低停顿、标记清除、老年代收集器
缺点:产生大量空间碎片**、**并发阶段会降低吞吐量
初始标记 停顿
并发标记
重新标记 停顿
并发清除
-XX:+UseConcMarkSweepGC
-XX:+ UseCMSCompactAtFullCollection **Full GC后,进行一次碎片整理;整理过程是独占的,会引起停顿时间变长
-XX:+CMSFullGCsBeforeCompaction **设置进行几次Full GC后,进行一次碎片整理
-XX:ParallelCMSThreads **设定CMS的线程数量(一般情况约等于可用CPU数量)
5.G1:空间整合、可预测停顿
将堆分成多个大小相等的独立区域
-XX:+UseG1GC
-XX:MaxGCPauseMillis =50 暂停时间目标
-XX:GCPauseIntervalMillis =200 暂停间隔目标
-XX:+G1YoungGenSize=512m 年轻代大小
-XX:SurvivorRatio=6 幸存区比例

 

jvm调优

FullGC之后查看老年代内存占用OU的大小
jstat -gc 12345
-Xms=Xmx=[3-4倍] 堆初始化和最大内存 堆空间大小
-Xmn=[1-1.5倍] 年轻代大空间大小
-XX:MetaspaceSize=MaxMetaspaceSize=[1.2-1.5倍] 永久代|元空间
老年代空间大小=堆空间大小-年轻代大空间大小=[2-3倍]


jvm
java堆大小设置,Xms 和 Xmx设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍
永久代 PermSize和MaxPermSize(元空间)设置为老年代存活对象的1.2-1.5倍。
年轻代Xmn的设置为老年代存活对象的1-1.5倍。
老年代的内存大小设置为老年代存活对象的2-3倍。
可以让系统运行一段时间后查看系统的各个指标,然后在进行配置。如下用jstat工具查看jvm的情况

jstat -gc 12345
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
13824.0 22528.0 13377.0 0.0 548864.0 535257.2 113152.0 46189.3 73984.0 71119.8 9728.0 9196.2 14 0.259 3 0.287 0.546

OU表示老年代所占用的内存为 46189.3 K(大约45M);那么jvm相应的配置参数应该做如下修改
-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M -Xms180m -Xmx180m -Xmn=[45m,1.5*45m]

-XX:MetaspaceSize=[1.2,1.5]*4.5m -XX:MaxMetaspaceSize=[1.2,1.5]*4.5m
-Xms=[3,4]*4.5m -Xmx=[3,4]*4.5m -Xmn=[1, 1.5]*4.5m

 

垃圾回收
新new的对象都放在Eden区(伊甸园嘛,创造的地方)
Eden区满或者快满的时候进行一次清理(Minor Gc),不被引用的对象直接被干掉;还有引用的对象,但是年龄比较大的,挪到S0区
下次Eden区快满的时候,会进行上一步的操作,并且将Eden和S0区的年纪大的对象放到S1区【原理上随时保持S0和S1有一个是空的,用来存下一次的对象】
下下次,Eden区快满的时候,会进行上一步操作,并且将Eden和S1区的年纪大的对象放到S0区【此时S1区就是空的】
直到Eden区快满,S0或者S1也快满的时候,这时候就把这两个区的年纪大的对象放到Old区
依次循环,直到Old区也快满的时候,Eden区也快满的时候,会对整个这一块内存区域进行一次大清洗(FullGC),腾出内存,为之后的对象创建,程序运行腾地方。
清理Eden区和Survivor区叫Minor GC;清理Old区叫Major GC;清理整个堆空间—包括年轻代和老年代叫Full GC。

 

JVM内存结构

jvm1.7内存结构:
1.方法区(共享)(PermGen永久代):
已经被jvm加载的类信息(Class)
常量(static final)
静态变量(static)
即时编译器编译后的代码(code)
2.堆(共享):
对象实例(obj)
数组(ary[])
3.栈(线程私有):
局部变量表(局部变量)
操作栈
动态联
方法出口(返回值)
4.程序计数器(线程私有):
字节码行号指示器

jvm1.8内存结构:
1.方法区(共享、本地内存)(元空间MetaSpace):
已经被jvm加载的类信息(Class)
常量(static final)
静态变量(static)
即时编译器编译后的代码
2.堆(共享):
对象实例(obj)
数组(ary[])
3.栈(线程私有):
局部变量表(局部变量)
操作栈
动态联
方法出口(返回值)
4.程序计数器(线程私有):
字节码行号指示器

 

posted on 2020-07-21 06:59  仙路尽头谁为峰  阅读(243)  评论(0编辑  收藏  举报
这里是自由发挥的天堂