尚硅谷2020最新版宋红康JVM教程学习笔记 七

点击查看合集

System.gc()

1.默认情况下,通过System.gc()或者Runtime.getRuntime().gc()的调用,会显式触发Full GC,同时对老年代和新生代进行回收,尝试释放被丢弃对象占用的内存。
在这里插入图片描述
这俩方法相同
2.System.gc()Runtime.getRuntime().gc()/调用附带一个免责声明,无法保证对垃圾收集器的调用(提醒JVM的垃圾回收器执行GC但是不一定会执行)
在这里插入图片描述

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

内存溢出(OOM)

没有空闲内存,并且垃圾收集器也无法提供更多内存。
除了程序计数器外,其他运行时数据区的部分都可能OOM

内存泄露(Memory Leak)

严格来说:对象不会再被程序用到了,但是GC又不能把他回收,就叫做内存泄漏。
宽泛来说:因为设计不当,导致某些对象生命周期过长,导致不能及时回收
例子:
1.把应该声明为局部变量的对象声明为类变量
2.在Web应用中,错把一些对象设置成会话范围。
3.某些对象已经不用了,但是忘记把他们之间的链接断开了。

在这里插入图片描述
4.单例对象引用了外部对象。因为单例对象的声明周期一般都是很长的,导致他引用的对象的声明周期也很长。
5.一些外部资源的连接对象没有及时关闭(close方法)如数据库连接 网络连接 io等

STW(Stop The World)

STW时,整个应用程序线程都会被暂停。
可达性分析算法中枚举根节点会导致STW
STW时间与采用那款GC无关,所有的GC都有这个事件。开发中不要用System.gc()会导致STW发生。STW是JVM在后台自动发起和自动完成的。

垃圾回收的并发与并行

并行:指多条垃圾收集线程并行工作,此时用户线程仍处于等待状态
如 ParNew 、Parallel、 Scavenge 、Parallel Old
串行:单线程执行回收完再启动程序线程
如 Serial 、Serial Old
并发:用户线程和垃圾回收线程在同一时间段内同时进行

引用

强引用

类似Object obj = new Object()这种引用关系,无论什么情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉引用的对象。

public class Test3 {
    
    
    public static void main(String[] args) {
    
    
        //创建强引用
        Test3 t3 = new Test3();
    }
}

软引用

在系统将要发生内存溢出前或者JVM检测到内存空间比较紧张时,将会把这些对象列入回收范围之中进行第二次回收。如果这次回收后还没有足够的内存,才会报OOM
软引用只有在内存不足时才会回收。因此可以用软引用保存缓存,当内存不足时清理掉,这样就既保证了使用缓存的同时,不会耗尽内存。

public class Test3 {
    
    
    public static void main(String[] args) {
    
    
    	//创建强引用
        Test3 t3 = new Test3();
        //创建软引用
        SoftReference<Test3> softReference = new SoftReference<Test3>(t3);
        //销毁强引用
        t3 = null;
    }
}

弱引用

当垃圾收集器工作时,无论内存空间是否足够,都会回收掉被弱引用关联的对象。

public class Test3 {
    
    
    public static void main(String[] args) {
    
    
        Test3 t3 = new Test3();
        //创建弱引用
        WeakReference<Test3> weakReference = new WeakReference<Test3>(t3);
        //销毁强引用
        t3 = null;
    }
}

虚引用

无法通过虚引用来获得对象实例,虚引用也不会影响生命周期。为一个对象设置虚引用的目的是能在这个对象被收集器回收时收到一个系统通知。
虚引用必须和引用队列一起使用。当被虚引用的对象被回收后,将这个虚引用加入引用队列,来通知应用程序对象的回收情况。
由于虚引用可以跟踪对象的回收时间,因此也可以将一些资源释放操作放置在虚引用中执行和记录。

public class Test3 {
    
    
    public static void main(String[] args) {
    
    
        Test3 t3 = new Test3();
        //创建应用队列
        ReferenceQueue queue = new ReferenceQueue();
        //创建虚引用
        PhantomReference<Test3> phantomReference = new PhantomReference<>(t3,queue);
        //销毁强引用
        t3 = null;
        //get方法无法获取对象
        System.out.println(phantomReference.get());//输出null
    }
}

猜你喜欢

转载自blog.csdn.net/qq_30033509/article/details/111066347