手记

【九月打卡】第21天 JVM垃圾回收

课程名称Java架构师-技术专家
课程章节JVM性能调优-理论+工具篇
课程讲师:慕课讲师团

课程内容

什么场景下使用什么垃圾回收策略?

在对内存要求苛刻的场景:想办法提高对象的回收效率,多回收掉一些对象,腾出更多内存
在CPU使用率较高的情况下:降低高并发时垃圾回收的频率,让CPU更多地去执行你的业务而不是垃圾回收

垃圾回收发生在那些区域?


虚拟机栈、本地方法栈、程序计数器都是线程独享的,这三个区域随着线程的创建而创建,随着线程的销毁而销毁。而栈里面的栈帧又会随着方法的方法的调用和返回分别进行入栈和出栈的操作。所以这三块区域是不需要考虑垃圾回收的。

堆和方法区是线程共享的,这两块区域才需要考虑垃圾回收,堆是垃圾回收的主要区域,主要回收的是创建的对象;方法区主要回收的是废弃的常量以及不需要使用的类。

对象在什么时候能够被回收?

有两种算法可以判断对象是不是可以回收:

引用计数法

通过对象的引用计数器来判断给对象是否被引用

如果出现循环引用,引用计数法就无能为力了。

所以 Java 并没有使用引用计数法

可达性分析

以根对象(GC Roots)作为起点向下搜索,走过的路径被称为引用链(Reference Chain),如果某个对象到根对象没有引用链相连时,就认为这个对象是不可达的,可以回收。

GC Roots 包含那些对象?

  • 虚拟机栈(栈帧中的本地变量表)中引用的变量
  • 方法区中类静态属性引用的变量
  • 方法区中常量所引用的对象
  • 本地方法栈(即Native方法)引用的对象

引用

强引用(Strong Reference)

  • 形如 Object obj= new Object() 的引用,就是平时使用的引用
  • 只要强引用在,永远不会回收被引用的对象,哪怕是出现内存溢出

软引用(Soft Reference)

  • 形如SoftReference sr=new SoftReference<>(“hello”)
  • 是用来描述一些有用但非必须的对象
  • 软引用关联的对象,只有在内存不足的时候才会回收,利用这个特性,软引用就比较适合实现缓存,比如网页缓存,图片缓存等等。

弱引用(Weak Reference)

  • 形如 WeakReference sr=new WeakReference<>(“hello”)
  • 弱引用也是用来描述非必须对象的
  • 无论内存是否充足,都会回收弱引用关联的对象
    一个对象即使不可达,也不一定会被回收
package theory;
//1. 避免使用 finalize 方法,操作不当可能会导致问题
//2. finalized 方法优先级低,何时会被调用无法确定,因为什么时间发生GC不确定
//3. 建议使用 try-catch-finally 来替代 finalize方法
public class GCTest1 {
    private static GCTest1 obj;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize被调用了");
        obj = this; //重新创建了对象的引用,就会导致对象从 F-Queue中移除,没有被回收
    }

    /**
     * finalize被调用了
     * obj可用
     * obj==null
     *
     *
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        obj = new GCTest1();
        obj = null;
        System.gc();

        Thread.sleep(1000L);
        if (obj == null) {
            System.out.println("obj==null");
        } else {
            System.out.println("obj可用");
        }
        Thread.sleep(1000L);
        obj = null;//第二次如果不设置为 null 的话,就会导致 obj对象永远无法回收,
        System.gc();//因为之前已经调用过finalize方法,所以会走不必要分支
        if (obj == null) {
            System.out.println("obj==null");
        } else {
            System.out.println("obj可用");
        }
    }
}

课程收获

今天学习了JVM垃圾回收相关的概念知识。

0人推荐
随时随地看视频
慕课网APP