java基础知识JVM——强引用、软引用、弱引用与虚引用(含面试题)

强引用、软引用、弱引用与虚引用

强引用

使用new方法创造出来的对象,默认都是强引用。GC的时候,就算内存不够,抛出OutOfMemoryError也不会回收对象,死了也不回收。详见StrongReferenceDemo

public class StrongReferenceDemo {
    public static void main(String[] args) {
        Object o1=new Object();
        Object o2=new Object();
        o1=null;
        System.gc();
        System.out.println(o2);
    }
}

软引用

需要用Object.Reference.SoftReference来显示创建。如果内存够,GC的时候不回收内存不够则回收。常用于内存敏感的应用,比如高速缓存。详见SoftReferenceDemo
JVM配置单,故意产生大对象并配置小的内存,让它内存不够用导致OOM,看软引用的回收情况

条件1.创建大对象

 byte[] bytes = new byte[30 * 1024 * 1024];//一个30M的对象

条件2.配置小的内存的方法

IDEA菜单栏---Run---Edit Configurations ---VM options填写以下参数

 -Xms5m -Xmx5m -XX:+PrintGCDetails

最后,右键run运行。

配置图
在这里插入图片描述

代码

import java.lang.ref.SoftReference;

public class SoftReferenceDemo {
    public static void main(String[] args) {
        System.out.println("软引用内存充足的情况");
        softRef_Memory_Enough();
        System.out.println();
        System.out.println("软引用内存不足的情况");
        softRef_Memory_NotEnough();
    }

    /**
     * 内存够用的时候就保留,不够用就回收!
     */
    private static void softRef_Memory_Enough() {
        Object o1 = new Object();
        SoftReference<Object> softReference = new SoftReference<>(o1);
        System.out.println(o1);
        System.out.println(softReference.get());
        System.out.println("===========");
        o1 = null;
        System.gc();
        System.out.println(o1);
        System.out.println(softReference.get());
    }

    /**
     * JVM配置单,故意产生大对象并配置小的内存,让它内存不够用导致OOM,看软引用的回收情况
     * IDEA菜单栏---Run---Edit Configurations ---VM options---填写以下参数
     * -Xms5m -Xmx5m -XX:+PrintGCDetails
     * 右键run
     */
    private static void softRef_Memory_NotEnough() {
        Object o1 = new Object();
        SoftReference<Object> softReference = new SoftReference<>(o1);
        System.out.println(o1);
        System.out.println(softReference.get());
        System.out.println("===========");
        o1 = null;
        //System.gc();

        try {
            byte[] bytes = new byte[30 * 1024 * 1024];//一个30M的对象
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println(o1);
            System.out.println(softReference.get());
        }
    }
}

输出
在这里插入图片描述

弱引用

需要用Object.Reference.WeakReference来显示创建。无论内存够不够,GC的时候都回收,也可以用在高速缓存上。详见WeakReferenceDemo

代码

import java.lang.ref.WeakReference;

public class WeakReferenceDemo {
    public static void main(String[] args) {
        Object o1 = new Object();
        WeakReference<Object> weakReference = new WeakReference<>(o1);
        System.out.println(o1);
        System.out.println(weakReference.get());
        System.out.println("==========");
        o1 = null;
        System.gc();
        System.out.println(o1);
        System.out.println(weakReference.get());
    }
}

WeakHashMap

传统的HashMap就算key==null了,也不会回收键值对。但是如果是WeakHashMap,一旦内存不够用时,且key==null时,会回收这个键值对。详见WeakHashMapDemo

package jvm;

import java.util.HashMap;
import java.util.WeakHashMap;

public class WeakHashMapDemo {
    
    
    public static void main(String[] args) {
    
    
        myHashMap();
        System.out.println("===============");
        myWeakHashMap();
    }

    private static void myHashMap() {
    
    
        HashMap<Integer, String> map = new HashMap<>();
        Integer key = 1;
        String value = "HashMap";
        map.put(key, value);
        System.out.println(map);

        key = null;
        System.out.println(map);
        System.gc();
        System.out.println(map + "\t" + map.size());
    }

    private static void myWeakHashMap() {
    
    
        WeakHashMap<Integer, String> map = new WeakHashMap<>();
//        Integer key = 2;
        Integer key = new Integer(2);
        String value = "WeakHashMap";
        map.put(key, value);
        System.out.println(map);

        key = null;
        System.out.println(map);

        System.gc();
        System.out.println(map + "\t" + map.size());
    }
}

输出

{
    
    1=HashMap}
{
    
    1=HashMap}
{
    
    1=HashMap}	1
===============
{
    
    2=WeakHashMap}
{
    
    2=WeakHashMap}
{
    
    }	0

虚引用

软应用和弱引用可以通过get()方法获得对象,但是虚引用不行。虚引形同虚设,在任何时候都可能被GC,不能单独使用,必须配合引用队列(ReferenceQueue)来使用。设置虚引用的唯一目的,就是在这个对象被回收时,收到一个通知以便进行后续操作,有点像Spring的后置通知。详见PhantomReferenceDemo

引用队列

弱引用、虚引用被回收后,会被放到引用队列里面,通过poll方法可以得到。关于引用队列和弱、虚引用的配合使用,见ReferenceQueueDemo

代码

package jvm;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class PhantomReferenceDemo {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        Object o1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        PhantomReference phantomReference = new PhantomReference(o1, referenceQueue);
        System.out.println(o1);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());

        System.out.println("===========");

        o1 = null;
        System.gc();
        Thread.sleep(500);
        System.out.println(o1);
        System.out.println(phantomReference.get());
        System.out.println(referenceQueue.poll());
    }
}

输出

java.lang.Object@1b6d3586
null
null
===========
null
null
java.lang.ref.PhantomReference@4554617c

软引用与弱引用的适用场景

假如有一个应用需要读取大量的本地图片

  • 如果每次读取图片都从硬盘读取则会严重影响性能,
  • 如果一次性全部加载到内存中又可能造成内存溢出。

这时使用软引用可以解决这个问题
设计思路是:用一个 HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,
JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题

Map<String, SoftReference<Bitmap>> image Cache= new Hash Map<String, SoftReference<Bitmap>>0)

总结

在这里插入图片描述

其他

Integer中=和new 创建的区别

猜你喜欢

转载自blog.csdn.net/e891377/article/details/108763147