jvm
一个 java 代码的执行流程
那么 哪个地方需要进行GC呢?
eg:
User user = new User()
那么这个
user ==》 存在 stack里
new User() =》 是在 Heap里
user -》new User() 是有一个 指针 有 stack 指向 Heap 的
GC 主要是 Heap 和 Method Area 这两个地方
GC :
1.哪些对象要被回收
2.什么时候被回收
3.采用什么方式回收
1.哪些对象要被回收
User user = new User()
哪些对象要被回收 是有一些方式 给他们找出来的
那么有哪几种方式判断一个对象是否能够被回收呢?
1. 引用计数法
2.枚举根节点可达性分析
引用计数法
弊端:
java里 都是
引用指向对象 或者 父类引用指向子类对象
eg:
User.java{
Address adress ;
getter /setter
}
user.setAddress(address)
比如说 User 里面的 java 方法 里面的Address 对象 通过 getset 方法 外面new 一个 Address 放进去的
那么 User 和 Address 之间必然是有关系的
而user.setAddress(address) 这个操作 引用一次 address 就会在 User对象 里面有个计数器 给他加1
那么不是0 就不会垃圾回收
还有一个问题:
如果存在相互引用了怎么办?
所以 这个 引用计数法 是有弊端的 了解即可 jdk现在不是使用它
枚举根节点可达性分析
什么是GC ROOT?
栈:引用
方法区:存类相关的东西 即static的东西 final (就是局部变量)
本地方法栈: native
GC算法
三种算法:
标记清除:
标记:就是从 GCROot 走 ==》找到可达的对象
清除:不可达的 干掉
复制 :
把内存分为两个区 ,在同一时间点只能使用一个区域
标记整理:
标记: 个标记清除的标记阶段一样
整理:
弥补了标记清除内存碎片问题 也弥补了 复制算法仅能使用一半内存的问题
但是 :
复制的效率是最高的
第四种
分代算法: 他综合前面的算法 是基于代进行管理的
先要了解:
夭折对象:一会就结束的对象
长寿对象:还是要死的
不死对象:什么对象不死呀?类的信息
标记清除
复制
那么这三种算法 分别使用在GC里面的 那些地方呢?
复制:使用在 新生代
标记整理:使用在 老年代
GC的种类:
minor gc 针对新生代的 young
major gc 针对老年代的
full gc 都有可能
eg:
spark 官网gc调优那块
To further tune garbage collection, we first need to understand some basic information about memory management in the JVM:
Java Heap space is divided in to two regions Young and Old. The Young generation is meant to hold short-lived objects while the Old generation is intended for objects with longer lifetimes.
The Young generation is further divided into three regions [Eden, Survivor1, Survivor2].
A simplified description of the garbage collection procedure: When Eden is full, a minor GC is run on Eden and objects that are alive from Eden and Survivor1 are copied to Survivor2. The Survivor regions are swapped. If an object is old enough or Survivor2 is full, it is moved to Old. Finally, when Old is close to full, a full GC is invoked.
一个对象足够老 什么叫足够老呢?
就是年龄 每一次gc 之后 年龄会 加1 默认是15 就是足够老
年轻代:
有eden,两片大小相同的 s 构成 当
一一般在eden分配对象的时候,超过age以及 to 区域满了 那么就移到 old里面去
即:
eden +s0 => s1 =>age +1
eden满了 出发首次gc 活的对象放在s0
如果eden又满了 eden活的+s0 活的 ==> 移到s1 导致 s1 变成s0 s0变成=》s1 还有 age +1
age 加到15 就移到 old
垃圾收集器
垃圾收集器不是垃圾回收算法哈:
而垃圾收集器 是我们工作中要用的 要怎么配置的!!!
种类:
串行垃圾收集器 :
一个线程进行垃圾回收
会遇到 stop the world
Program => GC => Program
并行垃圾收集器:
垃圾收集多线程进行垃圾回收
并发垃圾收集器:
你的程序线程 和垃圾收集器线程 同时执行(不一定是 同时跑的 可能是 交替跑 所以同时执行不确切)
G1垃圾收集器:
jdk9 默认g1
jdk8 默认的垃圾收集器是??是 Parallelgc
把heap 划分成不同的区域 然后并发的对这些区域进行垃圾回收
串行垃圾收集器
并行垃圾收集器
并发垃圾收集器:
该怎么用呢?
新生代
1.Serial 串行的
那么 old 对应也是 Serial 的
开启:
-XX:+UseSerialGC
测试:
代码 :
package gc.doublehappy;
import java.util.Random;
public class JVMApp {
public static void main(String[] args) {
/**
* -Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+UseSerialGC
*/
try{
String context = "doublehappy";
while (true) {
context += context + new Random().nextInt(111111)
+ new Random().nextInt(333333);
context.intern();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
结果:
[GC (Allocation Failure) [DefNew: 1664K->192K(1856K), 0.0018486 secs] 1664K->823K(5952K), 0.0018833 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 1856K->191K(1856K), 0.0014408 secs] 2487K->1379K(5952K), 0.0014668 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 1855K->191K(1856K), 0.0012928 secs] 3043K->1724K(5952K), 0.0013196 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 1810K->192K(1856K), 0.0011147 secs] 3342K->2254K(5952K), 0.0011455 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 1647K->24K(1856K), 0.0009379 secs] 3710K->3150K(5952K), 0.0009541 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 1451K->1451K(1856K), 0.0000091 secs][Tenured: 3126K->2801K(4096K), 0.0031579 secs] 4578K->2801K(5952K), [Metaspace: 3533K->3533K(1056768K)], 0.0031958 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew (promotion failed) : 1427K->1427K(1856K), 0.0002886 secs][Tenured: 2801K->3344K(4096K), 0.0025713 secs] 4229K->3344K(5952K), [Metaspace: 3535K->3535K(1056768K)], 0.0028871 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 1494K->1494K(1856K), 0.0000107 secs][Tenured: 3344K->2816K(4096K), 0.0027758 secs] 4839K->2816K(5952K), [Metaspace: 3544K->3544K(1056768K)], 0.0028165 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew (promotion failed) : 1395K->1395K(1856K), 0.0001622 secs][Tenured: 2816K->3307K(4096K), 0.0025930 secs] 4212K->3307K(5952K), [Metaspace: 3544K->3544K(1056768K)], 0.0027782 secs] [Times: user=0.03 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 3307K->3287K(4096K), 0.0026759 secs] 3307K->3287K(5952K), [Metaspace: 3544K->3544K(1056768K)], 0.0026933 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 1856K, used 48K [0x00000000ffa00000, 0x00000000ffc00000, 0x00000000ffc00000)
eden space 1664K, 2% used [0x00000000ffa00000, 0x00000000ffa0c360, 0x00000000ffba0000)
from space 192K, 0% used [0x00000000ffbd0000, 0x00000000ffbd0000, 0x00000000ffc00000)
to space 192K, 0% used [0x00000000ffba0000, 0x00000000ffba0000, 0x00000000ffbd0000)
tenured generation total 4096K, used 3287K [0x00000000ffc00000, 0x0000000100000000, 0x0000000100000000)
the space 4096K, 80% used [0x00000000ffc00000, 0x00000000fff35e90, 0x00000000fff36000, 0x0000000100000000)
Metaspace used 3576K, capacity 4498K, committed 4864K, reserved 1056768K
class space used 386K, capacity 390K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
at java.lang.StringBuilder.append(StringBuilder.java:208)
at gc.doublehappy.JVMApp.main(JVMApp.java:18)
分析:
DefNew 这个就是 新生代的 串行
Tenured 这个是描述 老年代的 串行
所以 如果是单线程 使用 Serial 是没有问题的 但是现在 生产上单线程 很少 尤其是在大数据场景下
所以新生代的垃圾回收器 间接的决定了 老年代的垃圾回收器
2.ParNew 并行的
新生代:多垃圾回收线程
那么 这个对应老年代 几个垃圾回收线程呢??
测试
-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+UseParNewGC
结果:
[GC (Allocation Failure) [ParNew: 1664K->192K(1856K), 0.0007836 secs] 1664K->880K(5952K), 0.0008191 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1856K->192K(1856K), 0.0008566 secs] 2544K->1470K(5952K), 0.0008838 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1856K->192K(1856K), 0.0007164 secs] 3134K->1889K(5952K), 0.0007472 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1832K->150K(1856K), 0.0006000 secs] 3529K->2454K(5952K), 0.0006241 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1588K->190K(1856K), 0.0005151 secs] 3891K->3331K(5952K), 0.0005329 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew (promotion failed): 1656K->1497K(1856K), 0.0004741 secs][Tenured: 4059K->2377K(4096K), 0.0033012 secs] 4796K->2377K(5952K), [Metaspace: 3538K->3538K(1056768K)], 0.0038065 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew (promotion failed): 1458K->1460K(1856K), 0.0003521 secs][Tenured: 3771K->3074K(4096K), 0.0023408 secs] 3836K->3074K(5952K), [Metaspace: 3540K->3540K(1056768K)], 0.0027217 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1425K->1425K(1856K), 0.0000107 secs][Tenured: 3074K->2726K(4096K), 0.0025354 secs] 4500K->2726K(5952K), [Metaspace: 3541K->3541K(1056768K)], 0.0025729 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew (promotion failed): 1393K->1393K(1856K), 0.0003233 secs][Tenured: 2726K->3305K(4096K), 0.0029696 secs] 4120K->3305K(5952K), [Metaspace: 3541K->3541K(1056768K)], 0.0033217 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 3305K->3285K(4096K), 0.0030249 secs] 3305K->3285K(5952K), [Metaspace: 3541K->3541K(1056768K)], 0.0030450 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
par new generation total 1856K, used 49K [0x00000000ffa00000, 0x00000000ffc00000, 0x00000000ffc00000)
eden space 1664K, 2% used [0x00000000ffa00000, 0x00000000ffa0c440, 0x00000000ffba0000)
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
from space 192K, 0% used [0x00000000ffba0000, 0x00000000ffba0000, 0x00000000ffbd0000)
to space 192K, 0% used [0x00000000ffbd0000, 0x00000000ffbd0000, 0x00000000ffc00000)
at java.util.Arrays.copyOf(Arrays.java:3332)
tenured generation total 4096K, used 3285K [0x00000000ffc00000, 0x0000000100000000, 0x0000000100000000)
the space 4096K, 80% used [0x00000000ffc00000, 0x00000000fff357f0, 0x00000000fff35800, 0x0000000100000000)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
Metaspace used 3573K, capacity 4498K, committed 4864K, reserved 1056768K
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
class space used 386K, capacity 390K, committed 512K, reserved 1048576K
at java.lang.StringBuilder.append(StringBuilder.java:208)
at gc.doublehappy.JVMApp.main(JVMApp.java:18)
Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release
分析:
ParNew
tenured
所以 新生代使用并行的 老年代使用的 串行 一个线程来跑
新生代: 复制
老年代 : 标记整理
3.Parallel Scavenge 并发的
新生代:使用多垃圾回收线程
测试:
-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+UseParallelGC
结果:
[GC (Allocation Failure) [PSYoungGen: 1024K->488K(1536K)] 1024K->760K(5632K), 0.0009347 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1512K->480K(1536K)] 1784K->1126K(5632K), 0.0083649 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 1504K->480K(1536K)] 2150K->1476K(5632K), 0.0160808 secs] [Times: user=0.09 sys=0.00, real=0.02 secs]
[GC (Allocation Failure) [PSYoungGen: 1482K->496K(1536K)] 2478K->1961K(5632K), 0.0009932 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1520K->496K(1536K)] 2985K->2105K(5632K), 0.0015347 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1466K->480K(1536K)] 3074K->2272K(5632K), 0.0010472 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1455K->493K(1536K)] 3246K->2771K(5632K), 0.0006245 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1208K->384K(1536K)] 4181K->3840K(5632K), 0.0004184 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 384K->0K(1536K)] [ParOldGen: 3456K->1857K(4096K)] 3840K->1857K(5632K), [Metaspace: 3533K->3533K(1056768K)], 0.0106800 secs] [Times: user=0.19 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 387K->0K(1536K)] [ParOldGen: 3943K->2971K(4096K)] 4331K->2971K(5632K), [Metaspace: 3539K->3539K(1056768K)], 0.0055603 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 725K->0K(1536K)] [ParOldGen: 3666K->2603K(4096K)] 4392K->2603K(5632K), [Metaspace: 3541K->3541K(1056768K)], 0.0109824 secs] [Times: user=0.19 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 3994K->3993K(5632K), 0.0003450 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 3993K->3298K(4096K)] 3993K->3298K(5632K), [Metaspace: 3541K->3541K(1056768K)], 0.0035175 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 3298K->3298K(5632K), 0.0002787 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) Exception in thread "main" [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 3298K->3278K(4096K)] 3298K->3278K(5632K), [Metaspace: 3541K->3541K(1056768K)], 0.0099880 secs] [Times: user=0.20 sys=0.00, real=0.01 secs]
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
at java.lang.StringBuilder.append(StringBuilder.java:208)
at gc.doublehappy.JVMApp.main(JVMApp.java:18)
Heap
PSYoungGen total 1536K, used 50K [0x00000000ffe00000, 0x0000000100000000, 0x0000000100000000)
eden space 1024K, 4% used [0x00000000ffe00000,0x00000000ffe0ca38,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 4096K, used 3278K [0x00000000ffa00000, 0x00000000ffe00000, 0x00000000ffe00000)
object space 4096K, 80% used [0x00000000ffa00000,0x00000000ffd33b30,0x00000000ffe00000)
Metaspace used 3573K, capacity 4498K, committed 4864K, reserved 1056768K
class space used 386K, capacity 390K, committed 512K, reserved 1048576K
Process finished with exit code 1
分析:
PSYoungGen
ParOldGen
老年代使用的是 ParOldGen 多垃圾回收线程
新生代:复制
老年代:标记整理
使用场景:
吞吐量 = 程序时间 /(程序时间+GC时间)
eg:
程序运行了100分钟 gc用了 1分钟
100/101 = 99.
spark离线处理 使用这个 并发 是可以的 吞吐量可以
老年代
1.Serial old 串行的 单线程的
命令:
-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+UseSerialOldGC
注意哈 :
这是配置old
之前配置的young 老年代那块默认分配的
结果:
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
Unrecognized VM option 'UseSerialOldGC'
Did you mean '(+/-)UseSerialGC'?
因为UseSerialOldGC 在 jdk8 这个没有了 反过来走是没有的
2.Parallel Old
多线程的
命令:
-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+UseParallelOldGC
结果:
[GC (Allocation Failure) [PSYoungGen: 1024K->488K(1536K)] 1024K->748K(5632K), 0.0007666 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1512K->488K(1536K)] 1772K->1032K(5632K), 0.0143349 secs] [Times: user=0.11 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 1512K->496K(1536K)] 2056K->1483K(5632K), 0.0166682 secs] [Times: user=0.13 sys=0.00, real=0.02 secs]
[GC (Allocation Failure) [PSYoungGen: 1498K->496K(1536K)] 2485K->1838K(5632K), 0.0014980 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1520K->480K(1536K)] 2862K->1978K(5632K), 0.0012422 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1486K->496K(1536K)] 2984K->2200K(5632K), 0.0034311 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1344K->485K(1536K)] 3048K->2708K(5632K), 0.0005139 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1497K->288K(1536K)] 3719K->3325K(5632K), 0.0009387 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 966K->0K(1536K)] [ParOldGen: 3701K->2447K(4096K)] 4667K->2447K(5632K), [Metaspace: 3533K->3533K(1056768K)], 0.0098945 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 721K->0K(1536K)] [ParOldGen: 3774K->1885K(4096K)] 4495K->1885K(5632K), [Metaspace: 3541K->3541K(1056768K)], 0.0134680 secs] [Times: user=0.16 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 681K->0K(1536K)] 3893K->3212K(5632K), 0.0003513 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 3212K->3212K(5632K), 0.0002708 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 3212K->3203K(4096K)] 3212K->3203K(5632K), [Metaspace: 3541K->3541K(1056768K)], 0.0119428 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 3203K->3203K(5632K), 0.0002882 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
at java.lang.StringBuilder.append(StringBuilder.java:208)
at gc.doublehappy.JVMApp.main(JVMApp.java:18)
[PSYoungGen: 0K->0K(1536K)] [ParOldGen: 3203K->3183K(4096K)] 3203K->3183K(5632K), [Metaspace: 3541K->3541K(1056768K)], 0.0101996 secs] [Times: user=0.17 sys=0.00, real=0.01 secs]
Heap
PSYoungGen total 1536K, used 48K [0x00000000ffe00000, 0x0000000100000000, 0x0000000100000000)
eden space 1024K, 4% used [0x00000000ffe00000,0x00000000ffe0c320,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
to space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
ParOldGen total 4096K, used 3183K [0x00000000ffa00000, 0x00000000ffe00000, 0x00000000ffe00000)
object space 4096K, 77% used [0x00000000ffa00000,0x00000000ffd1bd98,0x00000000ffe00000)
Metaspace used 3573K, capacity 4498K, committed 4864K, reserved 1056768K
class space used 386K, capacity 390K, committed 512K, reserved 1048576K
所以和上面的对上了
最开始的那张图片对上了
3.CMS
并发标记清除
Concurrent Mark Sweep
目的:
停顿时间短
gc log dump下来可以查看自己的代码是否有问题!!!!
命令:
-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC
结果:
[GC (Allocation Failure) [ParNew: 1088K->128K(1216K), 0.0032096 secs] 1088K->744K(6016K), 0.0032570 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1216K->127K(1216K), 0.0310264 secs] 1832K->1123K(6016K), 0.0310603 secs] [Times: user=0.13 sys=0.02, real=0.03 secs]
[GC (Allocation Failure) [ParNew: 1215K->128K(1216K), 0.0011214 secs] 2210K->1416K(6016K), 0.0011566 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1212K->128K(1216K), 0.0007232 secs] 2500K->1728K(6016K), 0.0007547 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1193K->128K(1216K), 0.0121169 secs] 2794K->1886K(6016K), 0.0121512 secs] [Times: user=0.17 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [ParNew: 1076K->106K(1216K), 0.0004895 secs] 2834K->2186K(6016K), 0.0005072 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1188K->4K(1216K), 0.0004145 secs] 3268K->2704K(6016K), 0.0004314 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Initial Mark) [1 CMS-initial-mark: 2699K(4800K)] 3411K(6016K), 0.0001437 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-mark-start]
[GC (Allocation Failure) [ParNew: 1086K->4K(1216K), 0.0003857 secs] 3786K->3057K(6016K), 0.0004038 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-mark: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Final Remark) [YG occupancy: 1086 K (1216 K)][Rescan (parallel) , 0.0001334 secs][weak refs processing, 0.0000470 secs][class unloading, 0.0003268 secs][scrub symbol table, 0.0005921 secs][scrub string table, 0.0001034 secs][1 CMS-remark: 3053K(4800K)] 4140K(6016K), 0.0012553 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-sweep-start]
[GC (Allocation Failure) [ParNew: 1086K->6K(1216K), 0.0005818 secs][CMS[CMS-concurrent-sweep: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
(concurrent mode failure): 3761K->2471K(4800K), 0.0037437 secs] 4140K->2471K(6016K), [Metaspace: 3534K->3534K(1056768K)], 0.0043611 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 772K->6K(1216K), 0.0004532 secs] 4659K->4602K(6016K), 0.0004761 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Initial Mark) [1 CMS-initial-mark: 4596K(4800K)] 5310K(6016K), 0.0001093 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-mark-start]
[GC (Allocation Failure) [ParNew: 735K->735K(1216K), 0.0000111 secs][CMS[CMS-concurrent-mark: 0.001/0.001 secs] [Times: user=0.06 sys=0.02, real=0.00 secs]
(concurrent mode failure): 4596K->2639K(4800K), 0.0045237 secs] 5331K->2639K(6016K), [Metaspace: 3541K->3541K(1056768K)], 0.0045624 secs] [Times: user=0.06 sys=0.02, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 0K->0K(1216K), 0.0002349 secs][CMS: 4055K->3342K(4800K), 0.0030407 secs] 4055K->3342K(6016K), [Metaspace: 3541K->3541K(1056768K)], 0.0033071 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [CMS: 3342K->3323K(4800K), 0.0030466 secs] 3342K->3323K(6016K), [Metaspace: 3541K->3541K(1056768K)], 0.0030703 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Initial Mark) [1 CMS-initial-mark: 3323K(4800K)] 3323K(6016K), 0.0001121 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-mark-start]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
at java.lang.StringBuilder.append(StringBuilder.java:208)
at gc.doublehappy.JVMApp.main(JVMApp.java:18)
[CMS-concurrent-mark: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Final Remark) [YG occupancy: 53 K (1216 K)][Rescan (parallel) , 0.0001318 secs][weak refs processing, 0.0000055 secs][class unloading, 0.0001670 secs][scrub symbol table, 0.0002996 secs][scrub string table, 0.0000999 secs][1 CMS-remark: 3323K(4800K)] 3376K(6016K), 0.0007441 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
par new generation total 1216K, used 53K [0x00000000ffa00000, 0x00000000ffb50000, 0x00000000ffb50000)
eden space 1088K, 4% used[CMS-concurrent-sweep-start]
[0x00000000ffa00000, 0x00000000ffa0d708, 0x00000000ffb10000)
from space 128K, 0% used [0x00000000ffb30000, 0x00000000ffb30000, 0x00000000ffb50000)
to space 128K, 0% used [0x00000000ffb10000, 0x00000000ffb10000, 0x00000000ffb30000)
concurrent mark-sweep generation total 4800K, used 3323K [0x00000000ffb50000, 0x0000000100000000, 0x0000000100000000)
Metaspace used 3573K, capacity 4498K, committed 4864K, reserved 1056768K
class space used 386K, capacity 390K, committed 512K, reserved 1048576K
分析:
par new generation
concurrent mark-sweep generation 这个是首选 也可能是 Serial old
如果 cms出问题 备用就是 Serial old
CMS:阶段
CMS Initial Mark :初始标记
GCRoot -> 找到关联对象 很快
需要stw 暂停吗? 会暂停的 时间很短
CMS-concurrent-mark: 并发标记
GCroot 和用户线程一起工作 不会 stw
CMS-remark:重新标记
为什么要重新标记呢?因为你的用户程序是在执行的
可能有部分已经标记的对象的状态又发生了变化 所以这块会 stw 时间很短
concurrent mark-sweep:清除
清除GCRoot不可达对象 和用户线程一起的 不会stw
根据标记结果直接清理垃圾即可
这四个阶段 什么阶段耗费性能 ?并发标记 、 清除
总体来说:
是并发的 中间会停 时间短
优点:
并发收集 停顿低
缺点:
1. 对于2,4 阶段是并发 处理的 对于cpu 压力比较大
eg:
如果老年代 内存被用光了 垃圾回收还没有完成怎么办?full gc
所以在内存被用光之前 要确保 垃圾回收要完成的!!
这个场景就是 cms出故障了 =》引出 备胎 Serial old (单线程的)
=》GC ===>这样 停顿时间就会很长
所以使用 CMS 必须保证 在老年代耗尽之前 完成 gc!!!
2.内存碎片
使用参数可以解决
-XX:CMSFullsGCBeforeCompaction 默认值是0 可以配置成8或10
多少次 cms之后进行一个整理(就是内存整理一下 )
cms是标记清除 还记得标记清除的流程吗??
1.gc root -> 找到不可达的
2.对不可达的进行 清除
如何选择??
单 SerialGC ×
多 追求吞吐量 使用吞吐量那个 jdk8默认 -XX:+UseParallelGC
多 准求停顿低的 使用cms -XX:+UseConcMarkSweepGC
G1比较复杂 后续再说