Cao workers Zatan: Hands take you read the JVM gc log

I. Introduction

This afternoon would have been in the water, suddenly saw a micro-channel contacts that red dots, read, blog should be a garden friend. Added later, the friend asked me a question:

 

I ask, what is the relationship between these two? Gc see this log, the moment my mind a little bit ignorant, ah, this may have to turn a book, Zhou Zhiming Java Virtual Machine that there are in this book speak of God, I decisively turned pdf, looking up, and soon ,found it:

 

FIG made in the above, 6762k is the capacity before the new generation gc, 1006k is new generation capacity after gc, 10m in (8m + 1m of the eden region from survivor region) 9216k is the size of the new generation.

 

Look back a few numbers, 6762K- "3455K (19456K), meaning that, before the GC, Java heap uses 6762K, after GC, Java heap uses 3455K, and 19456K is a whole heap of capacity (9m + old and the new generation s 10m).

 

It stands to reason, so explanation is sufficient, however, sharp-eyed, he raised the following issues (this probably means that, with my own words):

 

This is what he would embarrassing. . . How are inexplicable ah. . . Fear not the wrong ah book. . . After some research we, reached the same conclusion:

 

 Internet search, I feel are some theories, we feel no problem, I have a question? ? ? Remember watching Tiger bashing posts before, someone posted that Zhejiang is rich, no poor (really rich), Zhejiang User response: Zhejiang far as I am a poor man!

I feel that now is, we no problem, I have a question? ?

Of course, if I stop there, and will not write this, my friend and fiddle with it, or understand it more clearly gc log.

 

Second, the correct reading method gc log

Tips: We do not run out and I like the effect, remember to see your own break point yet.

Find a friend took his test code, very simple demo, as follows:

 1 import java.util.concurrent.TimeUnit;
 2 
 3 
 4 public class AllocationTest {
 5 
 6     public static final int _1MB = 1024 * 1024;
 7 
 8 
 9     public static void main(String[] args) throws InterruptedException {
10         byte[] allocation1, allocation2, allocation3, allocation4;
11 
12         allocation1 = new byte[2 * _1MB];
13         allocation2 = new byte[2 * _1MB];
14         allocation3 = new byte[2 * _1MB];
15         //触发Minor GC
16         allocation4 = new byte[4 * _1MB];
17     }
18 }

 

JVM参数如下:

 -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

 

我本地先跑了下,结果是下面这样的:

 

这个console,和这位朋友的也不一致,我这边连那行 gc 前后的堆大小的日志都没打。因为他发我的参数里,可以看出来,没有指定垃圾收集器,那就是用了默认垃圾收集器。 而默认的垃圾收集器在不同版本的电脑上、不同版本的 JVM 上可能不一致。为了方便统一认识,我就建议大家统一用 Serial new 收集器,于是加了下面参数:

-verbose:gc -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

 

这次再运行,确实可以打印出来了

 

这里,只是重现了和这位朋友一样的问题,但问题本身,还没解决.。基于有问题就DEBUG的习惯,在下面这行打了个断点:

 1 import java.util.concurrent.TimeUnit;
 2 
 3 public class AllocationTest {
 4 
 5     public static final int _1MB = 1024 * 1024;
 6 
 7     public static void main(String[] args) throws InterruptedException {
 8         byte[] allocation1, allocation2, allocation3, allocation4;
 9 
10         allocation1 = new byte[2 * _1MB];
11         allocation2 = new byte[2 * _1MB];
12         allocation3 = new byte[2 * _1MB];
13         //触发Minor GC
14         allocation4 = new byte[4 * _1MB];
15 
16         TimeUnit.SECONDS.sleep(100);
17     }
18 }

 

在16行打了个断点,断点停在 16 行以后,console 如下:

 

让我惊醒的是,这次只打了这一行,并没有打印下图这部分:

 

 其实这里已经可以分析出来 gc 的大体过程了,不过为了方便我们理解,我们可以加上以下 JVM 参数:

-verbose:gc -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+PrintGC  -XX:+PrintGCTimeStamps  -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintGCApplicationStoppedTime 

 

这次,断点依然如约停在了那一行,我们看看 console,首先,下面是 gc 前的堆占用情况

 

然后,看看 gc 后的情况:

 

这里,我们就可以看出来了, 那3个 2m 大的对象,一开始占用了 eden区,eden区总共只有8m,那就只剩2m(实际上没剩2m,因为jvm自己占了一部分),这时候,我们要分配一个 4m 大的对象,那,JVM 在收到这个分配 4m 内存的请求后,检查了 自身的 eden区,明显不够,那就 gc 吧,也没啥好gc 的,那三个2m的对象,生命周期还没结束,我们当前的线程堆栈还维持着对它们的强引用,肯定是没法回收了。 3个 2m 的对象,活过本次gc,本来要放到 to survivor 区,但是明显放不下,于是只好丢给 老年代了。

于是,老年代被占用了 6m 空间。

 

理清了上述过程,再看下面那行gc 日志:

 

大家可以拿计算器算下,1kb 都没差。6144 + 569 = 6713!有一种做对数学题的快感!

 

三、总结

计算机科学,真是一门实践的学问。道友们,一起加油! 欢迎有兴趣的铜须,加群一起学习!

Guess you like

Origin www.cnblogs.com/grey-wolf/p/11232968.html