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优化总结 -- 实战

查看整个JVM内存状态   jmap -heap [pid]

jvm优化总结 -- 实战

jvm优化总结 -- 实战

查看JVM堆中对象详细占用情况    jmap -histo [pid]

jvm优化总结 -- 实战

导出整个JVM 中内存信息,可以利用其它工具打开dump文件分析,例如jdk自带的visualvm工具,如下:

注意:由于第一种方式是一种事后方式,需要等待当前JVM出现问题后才能生成dmp文件,实时性不高,第二种方式在执行时,JVM是暂停服务的,所以对线上的运行会产生影响。所以建议第一种方式。

转载于:https://blog.****.net/hj7jay/article/details/67632039

https://jingyan.baidu.com/article/fa4125ace675f128ac7092cd.html

jconsole怎么连接远程tomcat

jvm优化总结 -- 实战

使用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空间,避免太多静态对象。

  •