JVM 调优

一、内存回收


 

Minor GC、Major GC、Full GC

Jvm回收:回收的内存一般包括(新生代、老年代、方法区)大部分回收的是新生代

HotSpot Vm回收分两大类型

1、部分收集:

                新生代收集(Minor GC/young GC):只是新生代(Edens0,s1)的垃圾回收

                老年代回收(major GC / Old GC ):只是老年代的垃圾回收

      混合收集  G1 GC 会用这种方式

2、整堆收集:回收整个java堆和方法区 (Full GC)

3、JVM新生代

 HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to)。默认比例为8:1

 1)新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定程度时,就会被移动到年老代中 

 2)新创建的对象基本存在于Eden取和From区(from和to均为 Survivor区)

 3)当GC后,Eden区中大部分对象都被回收,所有存活的对象通过复制算法复制到 to,from中还存活的对象根据年龄决定其去向,年龄达到阈值(可以通过-XX:MaxTenuringThreshold来设置)则移到老年代,否则被移到To区

 4)当老年代内存满了后会触发Full GC进行回收

二、性能监控及调优


 目的:防止出现OOM、解决OOM、减少Full GC出现的频率

2.1 设置堆内存大小,显示垃圾回收的详细信息

-Xms512M -Xmx512M -XX:+PrintGCDetails

 

 当老年代内存满了后触发一次full GC

2.2、怎样使对象进入老年代

第一种情况是当对象的年龄大小达到一定大小时就会就如老年代,对象的年龄是由对象经历GC的次数决定的,在新生代每次GC之后如果对象没有被回收则年龄加1,通过以下参数来设置最大年龄

-XX:MaxTenuring Threshod=15

第二种情况是大对象,JVM里面有一个参数可以设置对象的大小超过在指定的大小之后,直接晋升为老年代

-XX:PretenureSizeThreshold=80M

2.3堆空间常用参数 

查看所有参数的默认初始值:-XX:PrintFlagsInitial
查看所有参数的最终值:-XX:+PrintFlagsFinal
堆初始大小: -Xms
堆最大大小: -Xmx 或 -XX:MaxHeapSize=size
新生代大小: -Xmn 或 (-XX:NewSize=size + -XX:MaxNewSize=size )
配置新生代与老年代在堆结构的占比:-XX:NewRatio
设置新生代中Eden和s0/s1空间的比列:-XX:SurvivorRatio
设置新生代垃圾的最大年龄:-XX:MaxTenuringThreshould

幸存区比例 -XX:SurvivorRatio=ratio
晋升阈值 -XX:MaxTenuringThreshold=threshold
晋升详情 -XX:+PrintTenuringDistribution
输出详细的GC处理日志: -XX:+PrintGCDetails

打印简要信息:1 :-XX:+PrintGC 2:verbose:gc
FullGC 前 MinorGC -XX:+ScavengeBeforeFullGC
当堆空间溢出时在当前项目目录下面生成一个heapdump快照文件:-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

2.4内存分配与垃圾回收参数列表

-XX:+PrintGC 输出GC日志
-XX:+P[rintGCDetails 输出GC的详细日志
-XX:+PrintGCTimeStamps 输出GC的时间戳
-XX:+PrintGCDateStamps 输出GC的时间戳
-XX:+PrintHeapAtGC 在GC前后打印出堆的信息
-Xloggc:../logs/gc.log 日志文件的输出路径

 2.5性能优化

性能监控、性能分析、性能调优三个方面解决性能问题

常用工具:

1)jps查询正在运行的程序进程

常用参数:

-q 只显示pid,不显示class名称,jar文件名和传递给main 方法的参数

 -m 输出传递给main 方法的参数,在嵌入式jvm上可能是null

 -l 输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名

 

  jps -v

 2)jstat用于监控虚拟机的各种运行状态

可以显示本地或者远程虚拟机中的类装载、内存、垃圾收集、JIT编译等运行数据

jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

<interval> 用于指定统计数据的周期,单位为毫米(就是每隔多长时间统计一次)

-t 显示程序的运行时间

-class 监控加载类的情况

 3)Arthas

基础指令:

dashboard--当前系统的实时数据面板

thread --查看当前jvm的线程堆栈信息

jvm--查看当前jvm的信息

sysprop--查看和修改jvm的系统属性

sysenv--查看jvm的环境变量

vmoption--查看和修改jvm里诊断相关的option

getstatic--查看类的静态属性

heapdump--dump java head 

 

三、垃圾回收


 

3.1垃圾回收相关概念

system().gc或者Runtime().gc()的调用,会触发Full GC,同时对老年代和新生待进行回收,尝试释放被丢弃对象占用的内存

提醒jvm的垃圾回收器执行,但不一定立马执行

3.2 G1垃圾回收器的日志分析

2021-04-13T19:43:44.816+0800: 117950.759: [GC pause (G1 Evacuation Pause) (young), 0.0186948 secs]
   [Parallel Time: 13.4 ms, GC Workers: 4]
      [GC Worker Start (ms): Min: 117950761.1, Avg: 117950761.2, Max: 117950761.3, Diff: 0.2]
      [Ext Root Scanning (ms): Min: 6.4, Avg: 8.1, Max: 12.8, Diff: 6.4, Sum: 32.5]
      [Update RS (ms): Min: 0.0, Avg: 2.7, Max: 6.0, Diff: 6.0, Sum: 10.7]
         [Processed Buffers: Min: 0, Avg: 14.5, Max: 29, Diff: 29, Sum: 58]
      [Scan RS (ms): Min: 0.1, Avg: 0.2, Max: 0.4, Diff: 0.3, Sum: 0.9]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.1]
      [Object Copy (ms): Min: 0.0, Avg: 0.9, Max: 1.6, Diff: 1.6, Sum: 3.8]
      [Termination (ms): Min: 0.0, Avg: 1.1, Max: 2.1, Diff: 2.1, Sum: 4.4]
         [Termination Attempts: Min: 1, Avg: 19.8, Max: 38, Diff: 37, Sum: 79]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.1, Max: 0.1, Diff: 0.1, Sum: 0.4]
      [GC Worker Total (ms): Min: 13.1, Avg: 13.2, Max: 13.3, Diff: 0.2, Sum: 52.7]
      [GC Worker End (ms): Min: 117950774.3, Avg: 117950774.3, Max: 117950774.4, Diff: 0.0]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.5 ms]
   [Other: 4.8 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.4 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.1 ms]
      [Humongous Register: 1.3 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 2.1 ms]
   [Eden: 595.0M(595.0M)->0.0B(595.0M) Survivors: 1024.0K->1024.0K Heap: 918.7M(1024.0M)->323.4M(1024.0M)]
 [Times: user=0.03 sys=0.03, real=0.02 secs] 
2021-04-13T19:43:44.816+0800 :GC事件发生的时间
117950.759:JVM启动后经历的时间
GC pause (G1 Evacuation Pause):这个是收集器把存活对象从一个区域拷贝到另一个区域的阶段。
(young) 说明这是个YoungGC。
[Parallel Time: 13.4 ms, GC Workers: 4]:说明有4个GC线程
[Eden: 595.0M(595.0M)->0.0B(595.0M) Survivors: 1024.0K->1024.0K Heap: 918.7M(1024.0M)->323.4M(1024.0M)] 这一行说的是堆的大小变化。
 

四、内存相关


 

 4.1内存溢出

内存溢出(OOM):没有空闲内存,并且垃圾收集器也无法提供更多内存

 原因:

1)java堆内存设置不够:可以通过参数-Xms(堆初始化大小)、-Xmx(堆最大大小)来设置

 2)代码中有大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)

 4.2内存泄露

对象不会被程序用到了,但是GC又不能回收的情况

 五、对象引用


 

 引用分:强引用(strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)

除强引用外,其他3中均在JAVA.lang.ref包中

java中默认声明的就是强引用

Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收
obj = null;  //手动置null

java中强引用的关系只要还存在,垃圾回收就不能回收掉,即使OOM也不会,可以将强引用赋值为null,这样就可以被回收了

软引用

软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象

如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。

弱引用

弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收

在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。

虚引用

虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样

它随时可能会被回收,在 JDK1.2 之后,用 PhantomReference 类来表示

原文地址:https://www.cnblogs.com/anyanpeng/p/14626541.html