jvm调优

Posted 明镜止水丨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jvm调优相关的知识,希望对你有一定的参考价值。

JVM :Java虚拟机

Java 虚拟机:

数据类型:

数据类型分为两类:基本类型和引用类型。 基本类型:保存原始值(包括:byte,short,int,long,float,double,Boolean,returnAddres等);引用类型:保存引用值(包括 类类型,借口类型和数组)

堆与栈:(HEAP and STACK)

栈:运行的单位,储存的是方法

堆:存储的单位,储存的是对象

Java中 每一个线程对应一个独立的线程栈,而堆是所有线程共享的

java中 ,栈的大小 通过 -Xss 来设置,当栈中存储的数据比较多时,需要适当调整这个值,否则会出现java.lang.StackOverflowError异常。

 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

jvm结构:

 

1.当eden区 满了之后,触发 ygc(young gc):遍历eden区所有对象,是否还有引用指向他,把没有指向的对象直接回收掉,还有引用的 放到存活区s0,(这样伊甸园区变为空,有引用对象进入s0)

备注:在执行ygc ,整个应用程序线程是暂停的

2.第二次eden满了之后,执行ygc:

  a.遍历eden区所有对象,是否还有引用指向他,把没有指向的对象直接回收掉,还有引用的 放到存活区s1

  b.遍历存活区s0所有对象,是否还有引用指向他,把没有指向的对象直接回收掉,还有引用的 放到存活区s1

结果:eden和s0都清空

备注:s0与s1 是大小相等,来回互换,不会出现2个都有数据

jvm 默认的参数(可配置),如果ygc15次后 对象还存在,则在下次ygc的时候,该对象放入老年代,大对象,有参数设置的,超过多少后直接进老年代,不进eden

3.第步骤反复多次后,老年代满了后 ,执行:FULL GC :对整个 堆内存和非堆内存 执行 内存垃圾回收 ,耗时长,会影响性能,尽可能减少full gc 次数 

 结果: eden,s1 执行一次ygc ,老年代没有引用的干掉

 

4 .正常情况下 ,对象使用后 都应该是可以被回收的,当出现不可回收的对象,并把老年代沾满后就会出现内存溢出:java.lang.outofmemotyerror:java heap space

5.如果存活区放不了也,会当成大对象 直接从eden放到老年代

 

ycg:eden区满了,触发

full gc:老年代满了;持久带满了;system.gc();Runtime.getRuntime().gc() 触发 还有一些rmi框架会触发, 还有在执行 jmap -dump 命令 会触发 full gc 

 

 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 jdk 命令:

jmap -heap pid  查看 内存占用  (ps -aux|grep java ----pid) \\\\\\jmap 是内存中的命令 ,在~/bin 下要配置环境变量 

 

内存呗占用了 99.99999说明内存 泄露了

-------------------------------

jmap -histo pid >1.txt   

一般看前 20 就能知道是哪个堵塞 的 cn.test 包名 TsetBean 方法

------------------------------

如果 前 20 没有的话

jmap -dump:live,format=b,file=heap.bin <pid> 

live 还存活的对象 没有 :就是所有对象

file=文件名 可以改 

把 生成的文件 放到MemoryAnalyzer工具中去 ||||||||||||或者 (jhat -J-mx512m xxxx.bin 一般都不用这个了 ):会生成一个端口号 然后在浏览器中 输入 ip:端口 

---------------------------------------------------------------------------------------------------------------------------------------------------------------

jstack   当前线程栈正在调取的线程运信息  线程运行状态: new 新建 , RUNABLE 就绪 ,BLOCK 堵塞(死锁状态),WAITING 等待,DILE 死亡

jstack pid >2.txt

第一件事就是 搜索 BLOCK 死锁的线程:线程死锁错误

第二件事就是 搜索 WAITING ,(现象:响应很慢),很多的时候,就要注意(有可能是等待数据库链接池,就要看数据库链接池)

第三件事就是 搜索 RUNABLE, 主要分析 cpu (usr%高的时候)运行的:

先是找cup 运行最高的 进程 (top),然后找线程 top -H -p pid 找到 线程的 pid ,把这个线程 pid 转换成16进制 再去看线程栈 

或者 
ps -mp pid -o THREAD,tid,time 查看进程中的线程

 

找到 tid  转换成 16进制 printf "%x\\n" tid

然后 jstack pid |grep 16进制的 tid

(参考文档:http://note.youdao.com/share/?id=017ee3c5a0d41bffe74521f8dd463237&type=note)

 

备注:cup可以这么分析,io 还有 网络也可以这么分析,就是再出问题的时间点 看cup在处理什么线程方法 

----------------------------------------------------------------------------------------------------------

jstat -gcutil pid  xxx(没个多少秒监听一次)

查看jvm的使用情况

 ------------------------------------------------------------------------------------------------------------

代码中 可以解决内存溢出:(执行垃圾回收)

System.gc();
Runtime.getRuntime().gc();

 

 --------------------------------------------------------------------------------------------------------------

jconsole

进入 tomcat 下  /bin下  vim catalina.sh

JAVA_OPTS="-Xms256m -Xmx256m -Xss1024K -XX:PermSize=128m -XX:MaxPermSize=128m -Djava.rmi.server.hostname=192.168.189.129 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false" 

 

Xms :最小堆内存256

Xmx:最大堆内存256

Xss:每个线程栈大小

XX:PermSize:初始化持久带大小

XX:MaxPermSize:最大持久带大小

Djava.rmi.server.hostname=192.168.189.129 :用rmi协议 监控 192.168.189.129 

com.sun.management.jmxremote.port=1090 端口号1090

Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false :不适用用户名;不使用安全协议

 

 

 

 

 

以上是关于jvm调优的主要内容,如果未能解决你的问题,请参考以下文章

JVM调优经验分享

JVM性能调优1:JVM性能调优理论及实践(收集整理)

JVM性能调优

JVM性能调优

jvm性能调优都做了啥

JVM参数调优详解