jvm 07-java引用类型

java引用类型

  • 强引用:当内存不足的时候,都不会进行空间回收,最终JVM抛出OutOfMemoryError
  • 软引用:当内存不足的时候,进行对象的回收处理,往往用于高速缓存中
  • 弱引用:不管内存是否紧张,只要GC运行都会回收
  • 幽灵引用:和没引用一样。

强引用

  • JVM默认支持模式
  • 在引用期间内,如果该堆内存被指定的栈内存有联系,那该对象就无法被GC所回收
  • 一旦出现内存不足,就会出现OutOfMemoryError异常
  • 正因为强引用具备内存分配异常问题,因此尽量少实例化对象

测试程序:

package cn.liang.jvm;
import static org.hamcrest.CoreMatchers.nullValue;
import java.lang.ref.SoftReference;
public class referenceType2 {
  public static void main(String[] args) {
      Object object = new Object();
      Object ref = object;
      object = null;
      System.out.println("内存充足时进行gc回收:");
      System.gc();
      System.out.println(ref);
      System.out.println("内存不足时进行gc回收:");
      try {
          String string = "liangjingfu";
          while (true) {
              string += string + string;
              string.intern();    
          }
      } catch (Throwable e) {
      }
      System.out.println(ref);
  }
}

输出结果:

内存充足时进行gc回收:
java.lang.Object@7852e922
内存不足时进行gc回收:
java.lang.Object@7852e922

软引用

  • 在许多的开源组件中,往往会使用软引用作为缓存组件出现
  • 软引用不足时回收,不充足时不回收
  • 软引用需要一个单独的类来实现控制:java.lang.ref.SoftReference
    • 构造函数:public SoftReference(T referent)
    • 取出数据:public T get();

测试程序:

package cn.liang.jvm;
import static org.hamcrest.CoreMatchers.nullValue;
import java.lang.ref.SoftReference;
public class referenceType2 {
  public static void main(String[] args) {
      Object object = new Object();
      SoftReference<Object> ref = new SoftReference<Object>(object);
      object = null;
      System.out.println("内存充足时进行gc回收:");
      System.gc();
      System.out.println(ref.get());
      System.out.println("内存不足时进行gc回收:");
      try {
          String string = "liangjingfu";
          while (true) {
              string += string + string;
              string.intern();    
          }
      } catch (Throwable e) {
      }
      System.out.println(ref.get());
  }
}

输出结果:

内存充足时进行gc回收:
java.lang.Object@7852e922
内存不足时进行gc回收:
null

弱引用:

  • 只要一进行GC处理,那么所引用的对象将会立即回收
  • 弱引用需要使用Map接口的子类:java.util.WeakHashMap
  • java.lang.ref包中存在一个WeakReference子类

测试程序1:

package cn.liang.jvm;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType3 {
  public static void main(String[] args) {
      String keyString = new String("name");
      String valueString = new String("liang");
      Map<String, String> map = new WeakHashMap<String, String>();
      map.put(keyString, valueString);
      keyString = null;
      System.out.println("内存进行gc回收前:");
      System.out.println(map);
      System.out.println("内存进行gc回收后:");
      System.gc();
      System.out.println(map);
  }
}

输出结果:

内存进行gc回收前:
{name=liang}
内存进行gc回收后:
{}

测试程序2:

package cn.liang.jvm;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType3 {
  public static void main(String[] args) {
      String keyString = new String("liang");
      WeakReference<String> reference = new WeakReference<String>(keyString);
      keyString = null;
      System.out.println("内存进行gc回收前:");
      System.out.println(reference.get());
      System.gc();
      System.out.println("内存进行gc回收后:");
      System.out.println(reference.get());
  }
}

输出结果:

内存进行gc回收前:
liang
内存进行gc回收后:
null

引用队列

  • 主要是保存那些准备被回收的对象
  • 所有的对象的回收扫描都是从根对象开始的
  • 引用路径的设置即确定好哪些对象可以被回收后,设置相应的引用强度
  • 引用队列可避免非强引用对象所带来的内存引用问题,该对象被回收后会自动保存

  • 找到对象5有两个路径:
    • 对象1 --> 对象5(强 + 软)
    • 对象2 --> 对象5(强 + 弱)

测试程序:

package cn.liang.jvm;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType4 {

  public static void main(String[] args) throws Exception {
      Object obj = new Object();
      ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
      WeakReference<Object> reference = new WeakReference<Object>(obj,queue);
      System.out.println("内存进行gc回收前:");
      System.out.println(queue.poll());
      obj = null;
      System.gc();
      Thread.sleep(100);
      System.out.println("内存进行gc回收后,对象保存:");
      System.out.println(queue.poll());
  }
}

输出结果:

内存进行gc回收前:
null
内存进行gc回收后,对象保存:
java.lang.ref.WeakReference@7852e922

幽灵引用

  • 永远取不了的数据

测试程序:

package cn.liang.jvm;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType5 {
  public static void main(String[] args) throws Exception {
      Object obj = new Object();
      ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
      PhantomReference<Object> reference = new PhantomReference<Object>(obj,queue);
      System.gc();
      System.out.println("对象读取:");
      System.out.println(reference.get());
      System.out.println("对象保存后读取:");
      System.out.println(queue.poll());
  }
}

输出结果:

对象读取:
null
对象保存后读取:
null

猜你喜欢

转载自www.cnblogs.com/liangjingfu/p/10019175.html