jvm优化总结 -- 实战
jvm优化理论:
- JVM优化主要目的是 : 降低youngGC的频率、减少fullGC的次数 ,过多的yongGC和fullGC会占用很多系统资源,影响效率 。而影响内存效率最关键的是fullGC,因为他对整个堆内存进行整理了,占用了大量的资源 。
- 调优原则:
a . 让对象在新生代GC时被回收、
b. 让对象在新生代多存活一段时间
c .不要创建过大的对象及数组避免直接在老生代创建对象
=== 直接或者间接减少在老生代创建对象
设置参数:
- 针对JVM堆的设置大小,可以通过-Xms -Xmx限定其最小、最大值,为了防止垃圾收集器在最小、最大之间收缩堆而产生额外的时间,我们通常把最大、最小设置为相同的值
年轻代和年老代将根据默认的比例(1:2)分配堆内存,可以通过调整二者之间的比率NewRadio来调整二者之间的大小,也可以针对回收代,比如年轻代,通过 -XX:newSize -XX:MaxNewSize来设置其绝对大小。同样,为了防止年轻代的堆收缩,我们通常会把-XX:newSize -XX:MaxNewSize设置为同样大小
· 新生代的大小:-Xmn
· Eden区和Survivor区的比值:-XX:SurvivorRatio堆的初始空间:-Xms,可以推算出老生代的大小为-Xms减去-Xmn
· 堆的最大空间:-Xmx
-Xss设置每个线程可使用的内存大小。最大年龄阈值:-XX:MaxTenuringThreshold,即新生代转入老生代的存活次数
· 老生代和新生代的比值:-XX:NewRatio,例如该值为3,则表示新生代与老生代比值为1:-XX:PermSize、-XX:MaxPermSize
分配用来设置永久代的最小大小和最大大小。Java 8以后移除了方法区,取而代之的是本地元空间Metaspace,大小由-XX:MetaspaceSize和-XX:MaxMetaspaceSize调节。-XX:+PrintGCDetails 只在程序结束后打印
-XX:+PrintHeapAtGC 每次GC都打印
内存泄漏:
一、内存泄露前的一些现象:
1、每次垃圾回收的时间越来越长,由之前的10ms延长到50ms左右,FullGC的时间也有之前的0.5s延长到4、5s
2、FullGC的次数越来越多,最频繁时隔不到1分钟就进行一次FullGC
3、年老代的内存越来越大并且每次FullGC后年老代没有内存被释放
之后系统会无法响应新的请求,逐渐到达OutOfMemoryError的临界值,然后抛出内存溢出异常;
二、何时会抛出OutOfMemoryException内存溢出异常,并不是内存被耗空的时候才抛出
条件1:JVM98%的时间都花费在内存回收
条件2:每次回收的内存小于2%
满足这两个条件将触发OutOfMemoryException,这将会留给系统一个微小的间隙以做一些Down之前的操作,比如手动打印Heap Dump。
实战:
1、生成堆的dump文件
JVM的配置文件中配置:
例如:堆初始化大小,而堆最大大小
在应用启动时配置相关的参数 -XX:+HeapDumpOnOutOfMemoryError,当应用抛出OutOfMemoryError时生成dump文件。
在启动的时候,配置文件在哪个目录下面:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=目录+产生的时间.hprof
2、发现程序异常前通过执行指令,直接生成当前JVM的dmp文件,6214是指JVM的进程号
jps 如何查看jvm的进程号
查看整个JVM内存状态 jmap -heap [pid]
查看JVM堆中对象详细占用情况 jmap -histo [pid]
导出整个JVM 中内存信息,可以利用其它工具打开dump文件分析,例如jdk自带的visualvm工具,如下:
注意:由于第一种方式是一种事后方式,需要等待当前JVM出现问题后才能生成dmp文件,实时性不高,第二种方式在执行时,JVM是暂停服务的,所以对线上的运行会产生影响。所以建议第一种方式。
转载于:https://blog.****.net/hj7jay/article/details/67632039
https://jingyan.baidu.com/article/fa4125ace675f128ac7092cd.html
jconsole怎么连接远程tomcat
使用jconsole远程监控tomcat服务器
转https://blog.****.net/shamoshuizu/article/details/70598268
按照上述连接的操作是可以远程监控tomcat的,但是有几个注意点:
往catalina.sh添加的内容
JAVA_OPTS="-Djava.rmi.server.hostname=47.104.236.248 -Dcom.sun.management.jmxremote.port=8081 -Dcom.sun.management.jmxremote.rmi.port=8081 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
47.104.236.248 为你云服务器的ip ;
8081 不是你tomcat启动时配置的端口,也不能被占用
2、连接时不需要密码
结果:
问题:导致项目 404了
年轻代和老年代应该设置多大才合理?
年轻代和年老代设置多大才算合理?这个我问题毫无疑问是没有答案的,否则也就不会有调优。我们观察一下二者大小变化有哪些影响 ;
更大的年轻代必然导致更小的年老代,大的年轻代会延长普通GC的周期,但会增加每次GC的时间;小的年老代会导致更频繁的Full GC
更小的年轻代必然导致更大年老代,小的年轻代会导致普通GC很频繁,但每次的GC时间会更短;大的年老代会减少Full GC的频率
如何选择应该依赖应用程序对象生命周期的分布情况:
如果应用存在大量的临时对象,应该选择更大的年轻代;
如果存在相对较多的持久对象,年老代应该适当增大。
持久对象:例如手机银行后端项目启动过程中,会查询数据库产生很多持久化对象。
临时对象:用户查询订单,会产生订单对象
但很多应用都没有这样明显的特性,在抉择时应该根据以下两点:(A)本着Full GC尽量少的原则,让年老代尽量缓存常用对象,JVM的默认比例1:2也是这个道理 (B)通过观察应用一段时间,看其他在峰值时年老代会占多少内存,在不影响Full GC的前提下,根据实际情况加大年轻代,比如可以把比例控制在1:1。但应该给年老代至少预留1/3的增长空间
相关经验:
- 手动调用System.gc() ; 垃圾回收不要手动触发,尽量依靠JVM自身的机制。
Pemanet Generation空间不足
采取措施:增大Perm Gen空间,避免太多静态对象。