JVM&GC-System.gc()方法


前言

在默认情况下,System.gc()会显示直接触发Full GC,同时对老年代和新生代进行回收。而一般情况下,垃圾回收应该是自动进行的,无需手工触发,否则就太麻烦了。

示例

public class TestGC {
    public static void main(String[] args) {
        new TestGC();
        System.gc();
        System.runFinalization();
    }
}

如果在idea查看日志输出,需要在Run–>Edit Configuration–>VM Options中设置

-XX:+PrintGCDetails

打印结果

[GC (System.gc()) [PSYoungGen: 8489K->1707K(38400K)] 8489K->1715K(125952K), 0.0070544 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (System.gc()) [PSYoungGen: 1707K->0K(38400K)] [ParOldGen: 8K->1568K(87552K)] 1715K->1568K(125952K), [Metaspace: 3357K->3357K(1056768K)], 0.0228661 secs] [Times: user=0.03 sys=0.00, real=0.02 secs] 
Heap
 PSYoungGen      total 38400K, used 998K [0x00000000d5f00000, 0x00000000d8980000, 0x0000000100000000)
  eden space 33280K, 3% used [0x00000000d5f00000,0x00000000d5ff9b20,0x00000000d7f80000)
  from space 5120K, 0% used [0x00000000d7f80000,0x00000000d7f80000,0x00000000d8480000)
  to   space 5120K, 0% used [0x00000000d8480000,0x00000000d8480000,0x00000000d8980000)
 ParOldGen       total 87552K, used 1568K [0x0000000081c00000, 0x0000000087180000, 0x00000000d5f00000)
  object space 87552K, 1% used [0x0000000081c00000,0x0000000081d883f0,0x0000000087180000)
 Metaspace       used 3369K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 366K, capacity 388K, committed 512K, reserved 1048576K

在这个例子中,一个新的对象被创建,由于它没有被使用,所以该对象迅速地变为不可达(Unreachable)。
GC开头的说明此次垃圾回收为Minor GC,而Full GC开头的说明此次垃圾回收为stop-the-world的类型。
PSYoungGen表示年轻代,ParOldGen表示老年代。
方括号内的8489K->1707K(38400K)表示GC前该内存区域已使用容量->GC后该内存区域已使用容量(该内存区域总容量)。
方括号外的8489K->1715K(125952K)表示GC前Java堆已使用容量->GC后Java堆已使用容量(Java堆总容量)。
0.0070544 secs表示该内存区域本次GC所占用的时间,单位是秒。有的收集器会给出更具体的时间数据,如[Times: user=0.00 sys=0.00, real=0.01 secs],这里的user、sys、real与Linux的time命令所输出的时间含义一致,分别代表用户态消耗的CPU时间、内核态消耗的CPU时间、操作从开始到结束所经过的墙钟时间。CPU时间和墙钟时间的区别是,墙钟时间包括各种非运算的等待耗时,如等待磁盘I/O、等待线程阻塞,而CPU时间不包括这些耗时,但当系统有多CPU或者多核的话,多线程操作会叠加这些CPU时间,所以若看到user或sys时间超过real时间也是完全正常的。
eden、from、to表示年轻代中各区域的划分。
Metaspace表示元空间的大小,这里用的是JDK1.8,如果是JDK1.7则没有该区域。

默认情况下,即使System.gc()生效,他会使用传统的Full GC方式回收整个堆内存垃圾,而会忽略选项中的USeG1GC,比如我们设置-XX:+PrintGCDetails -XX:+UseG1GC,运行代码,输出结果如下:

[GC pause (G1 Evacuation Pause) (young), 0.0065937 secs]
   [Parallel Time: 1.2 ms, GC Workers: 4]
      [GC Worker Start (ms): Min: 262.2, Avg: 262.5, Max: 263.4, Diff: 1.2]
      [Ext Root Scanning (ms): Min: 0.0, Avg: 0.2, Max: 0.3, Diff: 0.3, Sum: 0.7]
      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Object Copy (ms): Min: 0.0, Avg: 0.7, Max: 0.9, Diff: 0.9, Sum: 2.7]
      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.2]
         [Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 4]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [GC Worker Total (ms): Min: 0.0, Avg: 0.9, Max: 1.2, Diff: 1.2, Sum: 3.6]
      [GC Worker End (ms): Min: 263.4, Avg: 263.4, Max: 263.4, Diff: 0.0]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.0 ms]
   [Other: 5.4 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 5.3 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.0 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]
   [Eden: 6144.0K(6144.0K)->0.0B(12.0M) Survivors: 0.0B->1024.0K Heap: 7086.4K(128.0M)->1579.0K(128.0M)]
 [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (System.gc())  2078K->1176K(8192K), 0.0057042 secs]
   [Eden: 1024.0K(12.0M)->0.0B(3072.0K) Survivors: 1024.0K->0.0B Heap: 2078.9K(128.0M)->1176.6K(8192.0K)], [Metaspace: 3358K->3358K(1056768K)]
 [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 garbage-first heap   total 8192K, used 1176K [0x0000000081c00000, 0x0000000081d00040, 0x0000000100000000)
  region size 1024K, 1 young (1024K), 0 survivors (0K)
 Metaspace       used 3368K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 366K, capacity 388K, committed 512K, reserved 1048576K

可以看出G1 GC并没有并发执行。打开虚拟机选项 -XX:+ExplicitGCInvokesConcurrent后可改变这种默认行为

[GC pause (System.gc()) (young) (initial-mark), 0.0017516 secs]
   [Parallel Time: 1.4 ms, GC Workers: 4]
      [GC Worker Start (ms): Min: 254.2, Avg: 254.3, Max: 254.5, Diff: 0.3]
      [Ext Root Scanning (ms): Min: 0.0, Avg: 0.4, Max: 1.4, Diff: 1.3, Sum: 1.8]
      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Object Copy (ms): Min: 0.0, Avg: 0.8, Max: 1.1, Diff: 1.0, Sum: 3.0]
      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
         [Termination Attempts: Min: 1, Avg: 28.3, Max: 47, Diff: 46, Sum: 113]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
      [GC Worker Total (ms): Min: 1.1, Avg: 1.3, Max: 1.4, Diff: 0.3, Sum: 5.0]
      [GC Worker End (ms): Min: 255.6, Avg: 255.6, Max: 255.6, Diff: 0.0]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.0 ms]
   [Other: 0.3 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.2 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.0 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]
   [Eden: 7168.0K(14.0M)->0.0B(12.0M) Survivors: 0.0B->2048.0K Heap: 7676.5K(128.0M)->1665.6K(128.0M)]
 [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC concurrent-root-region-scan-start]
[GC concurrent-root-region-scan-end, 0.0007669 secs]
[GC concurrent-mark-start]
[GC concurrent-mark-end, 0.0001007 secs]
[GC remark [Finalize Marking, 0.0000437 secs] [GC ref-proc, 0.0000645 secs] [Unloading, 0.0004621 secs], 0.0006229 secs]
 [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC cleanup 1665K->1665K(128M), 0.0001751 secs]
 [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 garbage-first heap   total 131072K, used 1665K [0x0000000081c00000, 0x0000000081d00400, 0x0000000100000000)
  region size 1024K, 3 young (3072K), 2 survivors (2048K)
 Metaspace       used 3373K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 366K, capacity 388K, committed 512K, reserved 1048576K

调用System.gc()也仅仅是一个请求垃圾回收的建议,JVM接收这个消息后并不是立即做垃圾回收,而是对几个垃圾回收算法做加权,使垃圾回收操作容易发生或者提早发生,或回收较多而已。


文章作者: LeePandar
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LeePandar !
评论
 上一篇
JVM&GC-通用术语 JVM&GC-通用术语
G1(Garbage First)G1是一个并行回收器,他把内存分割为很多不相关的区间(Region),每个区间可以属于老年代或者年轻代,并且每个年代区间可以是物理上不连续的。垃圾回收时都是需要停下应用程序,不然没有办法防止应用程序的干扰,
2020-07-19
下一篇 
JVM&GC-对象提升规则 JVM&GC-对象提升规则
前言虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在Eden区出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并将对象年龄设为1.对象在Survivor中每熬过一
2020-07-18
  目录