一、垃圾回收判断对象是否存活
(1)引用 计数算法
在对象添加一个用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,当引用失效的时候计数器的值 就-1
缺点 循环引用会有问题。
(2)可达性分析算法
从GCRoot开始访问是否能找到 能找到说明 是活 如果找不到则死亡。
作GCRoot的对象
a.虚拟机栈
b.方法区的类属性所引用的对象
c.方法区中常量所引用的对象
d.本地方法栈中引用的对象
(3)引用类型和可达性级别
a.强引用:最常见普通对象引用,只要还有强引用指向一个对象,就不会回收
b.软引用:JVM认为内存不足时,才会去试图回收软引用指向的对象。(缓存场景)
c.弱引用:虽然是引用,但是随时可能被 回收掉
d.虚引用:不能通过它访问对象。供了对象衩finalize后,执行指定逻辑的机制。
二、如何回收
(1).回收策略
a.标记-清除算法
两大问题:
效率问题
空间问题
b.复制算法
堆内存划分
新生代
Eden(伊甸园)
Survivor(存活区)
Tenured Gen
老年代
c.标记-整理算法
d.分代收集算法
(2)垃圾回收器
分代回收器:新生代 和老年代 比例是1:2
a.serial
新生代
最基本,发展最悠久
单线程垃圾收集
b.Parnew
新生代
复制算法
多线程垃圾收集
c.Paralle Scavenge 收集器
复制算法(新生代收集器)
多线程收集器
达到可控制的吞吐量
吞吐量:CPU用于运行用户代码的时间与cup消耗总时间的比值
吞吐量 = (执行用户代码时间) / (执行用户代码的时间 + 垃圾回收所占用的时间)
-XX:MaxGCPauseMIllis垃圾收集器最大停顿时间
-XX:GCTimeRatio 吞吐量大小
(0,100)
d.Cms收集器(Concurrent Mark Sweep)
老年代
工作过程:
初始标记
并发标记
重新标记
并发清理
一些大的对象可能直接进入老年代,不需要进入年轻代。
G1收集器
优势
并行与并发
分代收集
空间整合
可预测的停顿
步骤
初始标记
并发标记
最终标记
筛选回收
与cms比较
内存分配策略
优先分配到eden
a.配置使用serial收集器
-verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC
-verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC -Xmx20M -Xms10M -XX:SurvivorRatio=8
-XX:SurvivorRatio=8 SurvivorRatio的默认值为8,言外之意就是Survivor和Edon的比例是8:1:1
Minor GC ,Full GC 触发条件
Minor GC触发条件:当Eden区满时,触发Minor GC。
Full GC触发条件:
(1)调用System.gc时,系统建议执行Full GC,但是不必然执行
(2)老年代空间不足
(3)方法区空间不足
(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
大对象直接分配到老年代
XX:PretenureSizeThreshold=6M 的意思是超过这个值的时候,对象直接在old区分配内存
长期存活的对象分配到老年代
-XX:MaxTenuringThreshold (默认是15)
age 1+1
空间分配担保
如果
-XX:+HandlePromotionFailure
1、满足,minor gc是安全的,可以进行minor gc。
2、不满足,虚拟机查看HandlePromotionFailure参数:
(1)为true,允许担保失败,会继续检测老年代最大可用的连续空间>历次晋升到老年代对象的平均大小。若大 于,将尝试进行一次minor gc,若失败,则重新进行一次full gc
(2)为false,则不允许冒险,要进行full gc(对老年代进行gc)。
动态对象年龄判断
Jps详解
jvm 查看进程
jps -l
jps -m
jps -mlv
查询所有的信息
Jstat
监控进程的类装载 内存 垃圾收集,jit编译的信息。
jstat -gcutil 进程号
逃逸分析:分析对象的作用域
1.堆分配参数
在以下进行配置
-verbose:gc -XX:+PrintGCDetails
2.新生代的配置
Boolean 类型
+号表示开启
- 号表示关闭
配置:
-XX:+PrintGCDetails
运行:jinfo -flag PrintGCDetails -52552
运行结果: 表示已开启
-XX:+PrintGCDetails
kv设值类型
公式:-XX:属性key=属性值value值
-XX:MetaspaceSize=128
-XX:MaxTenuringThreshold=15
配置
-XX:MetaspaceSize=1024m
运行:
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=201326592 -XX:MaxHeapSize=3196059648 -XX:MaxNewSize=1065353216 -XX:MetaspaceSize=1073741824 -XX:MinHeapDeltaBytes=52428
8 -XX:NewSize=67108864 -XX:OldSize=134217728 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UsePara
llelGC
Command line: -XX:MetaspaceSize=1024m -javaagent:G:\software\install\idea\IntelliJ IDEA Community Edition 2017.2.5\lib\idea_rt.jar=62158:G:\software\install\idea\IntelliJ IDEA Commun
ity Edition 2017.2.5\bin -Dfile.encoding=UTF-8
两个经典参数:
-Xms 等价于 -XX:InitialHeapSize
-Xmx等价于 -XX:MaxHeapSize
第一种:查看参数盘点家底
jps
jinfo -flag 具体参数 java进程编号
jinfo -flags java进程编号
第二种 查看参数盘点家底(盘看家底查看JVM默认值)
-XX:+PrintFlagsInitial
公式:java -XX:+PrintFlagsInital -version
java -XX:+PrintFlagsInitial
主要查看修改更新
-XX:+PrintFlagsFinal
公式:java -XX:+PrintFlagsFinal-version
java -XX:+PrintFlagsFinal
= 没有修改过
:= 人为修改或jvm修改过
1.新生代收集器
- Serial收集器
| 工作区域 | 单线程/多线程 | 垃圾收集算法 |
|
---|---|---|---|---|
Serial收集器 (Stop the World) | 新生代 | 单线程 | 复制算法 | Client模式下的默认新生代收集器。 进行垃圾收集时,必须Stop the world,直到它收集结束。 -XX:+UseSerialGC |
- ParNew收集器
| 工作区域 | 单线程/多线程 | 垃圾收集算法 |
|
---|---|---|---|---|
ParNew收集器 (Serial收集器的多线程版本) (Stop the World) | 新生代 | 多线程 | 复制算法 | Server模式下的默认新生代收集器 |
- Parallel Scavenge收集器
| 工作区域 | 单线程/多线程 | 垃圾收集算法 |
|
---|---|---|---|---|
Parallel Scavenge收集器 (Stop the World) | 新生代 | 多线程 | 复制算法 | 吞吐量优先收集器 目标:控制吞吐量 吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间) 吞吐量越高说明CPU时间利用率越高。 JVM参数: -XX:MaxGCPauseMillis 控制最大垃圾收集时间 -XX:GCTimeRatio 控制吞吐量大小 -XX:+UseParallelGC -XX:+UseParallelOldGC |
2.老年代收集器
- Serial Old收集器
| 作用区域 | 单线程/多线程 | 垃圾收集算法 |
|
---|---|---|---|---|
Serial Old收集器 (Stop the World) | 老年代 | 单线程 | 标记整理算法 | 这个收集器的主要意义也是在于给Client模式下的虚拟机使用。 如果在Server模式下,主要两大用途: (1)在JDK1.5以及之前的版本中与Parallel Scavenge收集器搭配使用 (2)作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用 |
- Parallel Old收集器
| 作用区域 | 单线程/多线程 | 垃圾收集算法 |
|
---|---|---|---|---|
Parallel Old收集器 (Stop the World) | 老年代 | 多线程 | 标记整理算法 | Parallel Old 是Parallel Scavenge收集器的老年代版本。这个收集器在1.6中才开始提供。 在JDK1.5以及之前的版本中,Parallel Scavenge+Serial Old(单线程),无法充分利用多CPU的处理能力。1.6之后,终于有了名副其实的“吞吐量优先“收集器组合:Parallel Scavenge + Parallel Old。 |
- CMS收集器(Concurrent Mark Sweep)
| 作用区域 | 单线程/多线程 | 垃圾收集器算法 |
|
---|---|---|---|---|
CMS收集器 | 老年代 | 多线程 | 标记-清除算法 | 目标:最短回收停顿时间 优点:并发收集,低停顿 缺点: 1)CPU资源敏感。 在并发阶段,虽然不会导致用于线程停顿。但会因为占用了一部分CPU资源,导致用户应用程序变慢,吞吐量降低。 2)无法处理浮动垃圾 并发清理阶段,用户线程仍旧在运行并产生垃圾,这些产生的垃圾此次收集无法清理。 因此,需要预留一部分内存用于并发清理时用户程序使用。 解决方法: 当预留的内存不够时,将发生Concurrent Mode Failure,JVM启动后备预案,临时启用Serial Old进行老年代垃圾收集 -XX:CMSInitiatingOccupancyFraction 3)内存碎片问题 解决方法: -XX:CMSFullGCsBeforeCompaction 设置执行多少次不带压缩的Full GC后,运行一次带压缩的 (默认为0,表示每次Full GC都进行碎片整理) |
CMS在老年代的整个过程分为4个步骤:
| 阶段 | 描述 |
---|---|---|
1 | 初始标记 (Stop the World) | 仅仅标记GC Roots能直接关联到的对象,速度很快 |
2 | 重新标记 (Stop the World) | 修正并发标记阶段因用户程序继续运行而导致标记发生变动的那一部分标记记录。此阶段比初始标记阶段稍长,但远比并发标记阶段的时间短。 |
3 | 并发标记 | 对GC Roots非直接关联到的对象进行标记,在此阶段,并发标记线程与用户线程并发执行,标记可能发生变动 |
4 | 并发清除 |