本篇内容主要讲解“有哪些学习Java GC的基础”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“有哪些学习Java GC的基础”吧!
目录(Java GC 学习实践)
浅谈基础
1.1 运行时数据区(Java 1.8)
1.2 垃圾收集算法
1.3 垃圾收集器
解析 GC 日志
JVM 监控工具
Linux 监控相关
一、浅谈基础
1. 运行时数据区

1.1 程序计数器
1.2 虚拟机栈
(VM Stack)【线程隔离】
其描述的是Java方法执行的内存模型:【重点】每个方法执行的过程都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。方法调用到执行结束,对应着一个栈帧在虚拟机栈中入栈到出栈的过程;
【异常相关】如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。方法每次调用都会创建一个栈帧,然后栈帧压栈,总不能无限压栈吧(初看没看懂,搜了下,发现也有人没看懂,心里平衡点);
【异常相关】大部分虚拟机栈都可以动态扩展,如果扩展时无法申请到足够的内存,就会OOM。
代码示例,见文末 code01.StackOverflowError
1.3 本地方法栈
(Native Method Stack)【线程隔离】
与虚拟机栈的区别是,虚拟机栈执行java方法(字节码)服务;本非方法栈则为native方法服务;
【异常相关】StackOverflowError、OOM。
1.4 堆
(Heap)【线程共享】
GC堆(垃圾堆),是垃圾收集器管理的主要区域;
java1.8之后【年轻代、老年代】。
代码示例,见文末 code02.OOM-heap
1.5 元数据区
(Metaspace)【线程共享】
jvm config example: -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=50m
元数据区取代了永久代,本质上都是方法区的实现,用来存放虚拟机加载的类信息、常量、静态变量、JIT编译后的代码。
代码示例,见文末 code03.OOM-metaspace
2. 垃圾收集算法
3. 垃圾收集器
3.1 新生代收集器 Serial
3.2 新生代收集器 ParNew
【并行多线程】新生代收集器,复制算法,Serial收集器的多线程版本;
单CPU下,不会比Serial好;甚至双CPU都不能100%超越Serial;
Server模式下首选新生代收集器,重要原因是,他能和CMS(真正意义上的并发收集器)配合工作。
3.3 新生代收集器 Parallel Scavenge
3.4 老年代收集器 Serial Old
3.5 老年代收集器 Parallel Old
3.6 老年代收集器 CMS
【并发多线程】老年代收集器,基于标记 - 清除(初始 & 并发 & 重新 标记,并发清除);
关注点不一样,目标为可控的吞吐量(Throughput),其他的关注点是尽可能缩短GC STW时间;
并发低停顿;缺点:CPU资源非常敏感、无法处理浮动垃圾、基于标记清除多碎片。
3.7 G1收集器
二、解析GC日志
1. 完整GC日志
2019-11-04T16:05:43.267+0800: 147.981: [GC (Allocation Failure) [PSYoungGen: 150496K->5938K(147456K)] 198958K->57548K(202752K), 0.0304547 secs] [Times: user=0.05 sys=0.00, real=0.03 secs]
Heap after GC invocations=39 (full 3):
PSYoungGen total 147456K, used 5938K [0x00000000f6700000, 0x0000000100000000, 0x0000000100000000)
eden space 141312K, 0% used [0x00000000f6700000,0x00000000f6700000,0x00000000ff100000)
from space 6144K, 96% used [0x00000000ffa00000,0x00000000fffcc8f8,0x0000000100000000)
to space 7680K, 0% used [0x00000000ff100000,0x00000000ff100000,0x00000000ff880000)
ParOldGen total 55296K, used 51610K [0x00000000e3400000, 0x00000000e6a00000, 0x00000000f6700000)
object space 55296K, 93% used [0x00000000e3400000,0x00000000e6666870,0x00000000e6a00000)
Metaspace used 80445K, capacity 83414K, committed 83584K, reserved 1122304K
class space used 10018K, capacity 10577K, committed 10624K, reserved 1048576K
}
{Heap before GC invocations=40 (full 4):
PSYoungGen total 147456K, used 5938K [0x00000000f6700000, 0x0000000100000000, 0x0000000100000000)
eden space 141312K, 0% used [0x00000000f6700000,0x00000000f6700000,0x00000000ff100000)
from space 6144K, 96% used [0x00000000ffa00000,0x00000000fffcc8f8,0x0000000100000000)
to space 7680K, 0% used [0x00000000ff100000,0x00000000ff100000,0x00000000ff880000)
ParOldGen total 55296K, used 51610K [0x00000000e3400000, 0x00000000e6a00000, 0x00000000f6700000)
object space 55296K, 93% used [0x00000000e3400000,0x00000000e6666870,0x00000000e6a00000)
Metaspace used 80445K, capacity 83414K, committed 83584K, reserved 1122304K
class space used 10018K, capacity 10577K, committed 10624K, reserved 1048576K
=====================分割线==========================
2019-11-04T16:05:43.298+0800: 148.011: [Full GC (Ergonomics) [PSYoungGen: 5938K->0K(147456K)] [ParOldGen: 51610K->48605K(83968K)] 57548K->48605K(231424K), [Metaspace: 80445K->80445K(1122304K)], 0.3256949 secs] [Times: user=0.55 sys=0.00, real=0.32 secs]
=====================。。。==========================
2. 提取主要内容
2019-11-04T16:05:43.267+0800: 147.981: [GC (Allocation Failure) [PSYoungGen: 150496K->5938K(147456K)] 198958K->57548K(202752K), 0.0304547 secs] [Times: user=0.05 sys=0.00, real=0.03 secs]
2019-11-04T16:05:43.298+0800: 148.011: [Full GC (Ergonomics) [PSYoungGen: 5938K->0K(147456K)] [ParOldGen: 51610K->48605K(83968K)] 57548K->48605K(231424K), [Metaspace: 80445K->80445K(1122304K)], 0.3256949 secs] [Times: user=0.55 sys=0.00, real=0.32 secs]
3. 分析日志
147.981
和 148.011
: JVM启动以来经过的秒数
GC
和 Full GC
: 表示垃圾收集停顿类型。注意:不是用来区分新生代还是老年代的
GC (Allocation Failure)
Allocation Failure 指分配失败,也即空间不足;
Full GC (Ergonomics)
Ergonomics 可以理解为自适应,表示自动的调节STW时间和吞吐量之间的平衡;
Full GC (System)
调用 System.gc()
触发的GC。
[PSYoungGen: 150496K->5938K(147456K)]
[ParOldGen: 51610K->48605K(83968K)]
[XXXXXX: 150496K->5938K(147456K)]
198958K->57548K(202752K)
GC前Java堆已使用容量 -> GC后Java堆已使用容量(Java堆总容量)
0.0304547 secs
GC耗时合计(secs秒)
[Times: user=0.05 sys=0.00, real=0.03 secs]
用户态CPU耗时、内核态CPU耗时和墙钟时间
代码示例
code01.StackOverflowError
public class StackOverflowMain {
public static void main(String[] args) {
// will throw java.lang.StackOverflowError
Test test = new Test();
try {
test.increment();
} catch (StackOverflowError e) {
System.out.println("sof error, this count is " + test.count);
e.printStackTrace();
}
}
static class Test {
private static int count;
void increment() {
count++;
increment();
}
}
}
code02.OOM-heap
public class OOMMain {
private static String STR = "string";
/**
* -verbose:gc -XX:+HeapDumpOnOutOfMemoryError
* -XX:HeapDumpPath=C:\\Users\\User\\Desktop\\gc
* will throw oom by Java heap space
*/
public static void main(String[] args) {
List<String> list = new ArrayList<>();
while (true) {
list.add(STR += STR);
}
}
}
code03.OOM-metaspace
public class OOMByCglibMain {
/**
* -verbose:gc -XX:+HeapDumpOnOutOfMemoryError
* -XX:HeapDumpPath=C:\\Users\\User\\Desktop\\gc
* -XX:MetaspaceSize=9m -XX:MaxMetaspaceSize=9m
* will throw oom by Metaspace
*/
public static void main(String[] args) {
ClassLoadingMXBean loadingBean = ManagementFactory.getClassLoadingMXBean();
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMByCglibMain.class);
enhancer.setCallbackTypes(new Class[]{Dispatcher.class, MethodInterceptor.class});
enhancer.setCallbackFilter(new CallbackFilter() {
@Override
public int accept(Method method) {
return 1;
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
});
Class clazz = enhancer.createClass();
System.out.println(clazz.getName());
//显示数量信息(共加载过的类型数目,当前还有效的类型数目,已经被卸载的类型数目)
System.out.println("total: " + loadingBean.getTotalLoadedClassCount());
System.out.println("active: " + loadingBean.getLoadedClassCount());
System.out.println("unloaded: " + loadingBean.getUnloadedClassCount());
}
}
}
到此,相信大家对“有哪些学习Java GC的基础”有了更深的了解,不妨来实际操作一番吧!这里是天达云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!