JVM第十一章-垃圾回收相关概念

本文详细探讨了JVM中的垃圾回收机制,包括System.gc()的使用、内存溢出与内存泄漏的区别及其原因,以及Stop the World现象。文章介绍了并发与并行的概念,并讲解了HotSpot虚拟机的算法实现细节,如安全点、安全区域、记忆集与卡表。此外,文章还阐述了四种引用类型:强引用、软引用、弱引用和虚引用的特性及应用场景。
摘要由CSDN通过智能技术生成

1. System.gc() 的理解

  1. 在默认情况下,通过System.gc()者Runtime.getRuntime().gc() 的调用,会显式触发Full GC,同时对老年代和新生代进行回收,尝试释放被丢弃对象占用的内存。

  2. 然而System.gc()调用附带一个免责声明,无法保证对垃圾收集器的调用(不能确保立即生效)

  3. JVM实现者可以通过System.gc() 调用来决定JVM的GC行为。而一般情况下,垃圾回收应该是自动进行的,**无须手动触发,否则就太过于麻烦了。**在一些特殊情况下,如我们正在编写一个性能基准,我们可以在运行之间调用System.gc()

代码示例:手动执行 GC 操作

public class SystemGCTest {
   
    public static void main(String[] args) {
   
        new SystemGCTest();
        System.gc();//提醒jvm的垃圾回收器执行gc,但是不确定是否马上执行gc
        //与Runtime.getRuntime().gc();的作用一样。

//        System.runFinalization();//强制调用使用引用的对象的finalize()方法
    }
    //如果发生了GC,这个finalize()一定会被调用
    @Override
    protected void finalize() throws Throwable {
   
        super.finalize();
        System.out.println("SystemGCTest 重写了finalize()");
    }
}

输出结果不确定:有时候会调用 finalize() 方法,有时候并不会调用

SystemGCTest 重写了finalize()
或
空

手动 GC 理解不可达对象的回收行为

//加上参数:  -XX:+PrintGCDetails
public class LocalVarGC {
   
    public void localvarGC1() {
   
        byte[] buffer = new byte[10 * 1024 * 1024];//10MB
        System.gc();
    }

    public void localvarGC2() {
   
        byte[] buffer = new byte[10 * 1024 * 1024];
        buffer = null;
        System.gc();
    }

    public void localvarGC3() {
   
        {
   
            byte[] buffer = new byte[10 * 1024 * 1024];
        }
        System.gc();
    }

    public void localvarGC4() {
   
        {
   
            byte[] buffer = new byte[10 * 1024 * 1024];
        }
        int value = 10;
        System.gc();
    }

    public void localvarGC5() {
   
        localvarGC1();
        System.gc();
    }

    public static void main(String[] args) {
   
        LocalVarGC local = new LocalVarGC();
        //通过在main方法调用这几个方法进行测试
        local.localvarGC1();
    }
}

JVM参数:

-Xms256m -Xmx256m -XX:+PrintGCDetails -XX:PretenureSizeThreshold=15m

1、第四个参数是设置大对象直接进入老年代的阈值,由于我的电脑8G和视频里老师的电脑16G不太一样。我测试的时候10M的数组都是直接进入到了老年代,为了保持一样的效果,我同时设置了堆内存和大对象阈值,尽量和宋红康老师保持一致

2、我也查过了大对象阈值的默认值

我不太懂这个默认值为啥是0,我猜测可能是代表什么比例,目前也没有搜到相关的东西。这个不太重要,暂时就没有太深究,希望读者有知道的可以告知我一声。

看不懂GC日志请看笔者的 那篇文章

1、调用 localvarGC1() 方法

执行 System.gc() 仅仅是将年轻代的 buffer 数组对象放到了老年代,buffer对象仍然没有回收

[GC (System.gc()) [PSYoungGen: 15492K->10728K(76288K)] 15492K->11000K(251392K), 0.0066473 secs] [Times: user=0.08 sys=0.02, real=0.01 secs] 
[Full GC (System.gc()) [PSYoungGen: 10728K->0K(76288K)] [ParOldGen: 272K->10911K(175104K)] 11000K->10911K(251392K), [Metaspace: 3492K->3492K(1056768K)], 0.0097940 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 76288K, used 655K [0x00000000fab00000, 0x0000000100000000, 0x0000000100000000)
  eden space 65536K, 1% used [0x00000000fab00000,0x00000000faba3ee8,0x00000000feb00000)
  from space 10752K, 0% used [0x00000000feb00000,0x00000000feb00000,0x00000000ff580000)
  to   space 10752K, 0% used [0x00000000ff580000,0x00000000ff580000,0x0000000100000000)
 ParOldGen       total 175104K, used 10911K [0x00000000f0000000, 0x00000000fab00000, 0x00000000fab00000)
  object space 175104K,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值