强引用
1.JAVA中默认为强引用
Object obj = new Object(); //只要obj指向object对象,Object对象就不会被回收
obj = null; //置位null,被回收
软引用
1.软引用是用来描述一些非必需但仍然有用的对象。当内存足够的时候,软引用不会回收。只有在内存不够的情况下,才会回收软引用。当回收了软引用内存还是不够,会抛出内存溢出。这种特性常常被用作缓存技术,比如网页缓存,图片缓存等。
下面举例来说明强引用和软引用的区别
在运行java代码之前,设置虚拟机的运行内存 -Xms2M -Xmx3M初始内存为2M最大内存为3M。
使用强引用正常情况下
public class TestOOM {
public static void main(String[] args) {
testStrongReference();
}
private static void testStrongReference() {
// 当 new byte为 1M 时,程序运行正常
byte[] buff = new byte[1024 * 1024 * 2];
System.out.println("当强引用设置内存为2M的时候");
}
}
运行结果
正常输出:当强引用设置内存为2M的时候
使用强引用超出内存限制情况
public class TestOOM {
public static void main(String[] args) {
testStrongReference();
}
private static void testStrongReference() {
// 当 new byte为 1M 时,程序运行正常
byte[] buff = new byte[1024 * 1024 * 3];
System.out.println("当强引用设置内存为2M的时候");
}
}
运行结果
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.practise.workhome.TestOOM.testStrongReference(TestOOM.java:10)
at com.practise.workhome.TestOOM.main(TestOOM.java:5)
Process finished with exit code 1
使用软引用正常的情况下
1.使用软引用,连续创建2个大小为1M的字节数组,并且赋值为软引用
public class TestOOM {
private static List<Object> list = new ArrayList<>();
public static void main(String[] args) {
testSoftReference();
}
private static void testSoftReference() {
for (int i = 0; i < 2; i++) {
byte[] buff = new byte[1024 * 1024];
SoftReference<byte[]> sr = new SoftReference<>(buff);
list.add(sr);
}
for(int i=0; i < list.size(); i++){
Object obj = ((SoftReference) list.get(i)).get();
System.out.println(obj);
}
}
}
运行结果
[B@6d6f6e28
[B@135fbaa4
使用软引用异常的情况下
1.使用软引用连续创建3个1M的数组,并赋值为软引用
public class TestOOM {
private static List<Object> list = new ArrayList<>();
public static void main(String[] args) {
testSoftReference();
}
private static void testSoftReference() {
for (int i = 0; i < 3; i++) {
byte[] buff = new byte[1024 * 1024];
SoftReference<byte[]> sr = new SoftReference<>(buff);
list.add(sr);
}
for(int i=0; i < list.size(); i++){
Object obj = ((SoftReference) list.get(i)).get();
System.out.println(obj);
}
}
}
运行结果
null
null
[B@6d6f6e28
注意:在代码中buff是一个强引用,它最终是指向软引用,软引用被回收后编译器发现buff没有被使用,自行进行优化回收了。
如果我们将代码做下调整
public class TestOOM {
private static List<Object> list = new ArrayList<>();
public static void main(String[] args) {
testSoftReference();
}
private static void testSoftReference() {
byte[] buff = null;
for (int i = 0; i < 3; i++) {
buff = new byte[1024 * 1024];
SoftReference<byte[]> sr = new SoftReference<>(buff);
list.add(sr);
}
for(int i=0; i < list.size(); i++){
Object obj = ((SoftReference) list.get(i)).get();
System.out.println(obj);
}
}
}
运行结果
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.practise.workhome.TestOOM.testSoftReference(TestOOM.java:16)
at com.practise.workhome.TestOOM.main(TestOOM.java:11)
- 结论:当软引用超出内存,打印结果总是最后一个对象被保存,其他的obj全部被置空了;说明软引用在内存不足的情况下,会自动被回收。
弱引用
弱引用的引用强度比软引用更弱一些,无论内存是否足够,只要JVM开始垃圾回收被弱引用关联的对象都会被回收。
示例代码
public class TestOOM {
private static List<Object> list = new ArrayList<>();
public static void main(String[] args) {
testWeakReference();
}
private static void testWeakReference() {
for (int i = 0; i < 10; i++) {
byte[] buff = new byte[1024 * 1024];
WeakReference<byte[]> sr = new WeakReference<>(buff);
list.add(sr);
}
System.gc(); //主动通知垃圾回收
for(int i=0; i < list.size(); i++){
Object obj = ((WeakReference) list.get(i)).get();
System.out.println(obj);
}
}
}
运行结果
null
null
null
null
null
null
null
null
null
null
虚引用
虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用那么等同于没有。虚引用使用类PhantomReference来表示,这个类有一个构造方法和get()方法,而他的get()方法返回的是null,也就是说无法使用get获取任何对象,虚引用必须结合ReferenceQueue一起使用;
/*
* Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.lang.ref;
/**
* Phantom reference objects, which are enqueued after the collector
* determines that their referents may otherwise be reclaimed. Phantom
* references are most often used for scheduling pre-mortem cleanup actions in
* a more flexible way than is possible with the Java finalization mechanism.
*
* <p> If the garbage collector determines at a certain point in time that the
* referent of a phantom reference is <a
* href="package-summary.html#reachability">phantom reachable</a>, then at that
* time or at some later time it will enqueue the reference.
*
* <p> In order to ensure that a reclaimable object remains so, the referent of
* a phantom reference may not be retrieved: The <code>get</code> method of a
* phantom reference always returns <code>null</code>.
*
* <p> Unlike soft and weak references, phantom references are not
* automatically cleared by the garbage collector as they are enqueued. An
* object that is reachable via phantom references will remain so until all
* such references are cleared or themselves become unreachable.
*
* @author Mark Reinhold
* @since 1.2
*/
public class PhantomReference<T> extends Reference<T> {
/**
* Returns this reference object's referent. Because the referent of a
* phantom reference is always inaccessible, this method always returns
* <code>null</code>.
*
* @return <code>null</code>
*/
public T get() {
return null;
}
/**
* Creates a new phantom reference that refers to the given object and
* is registered with the given queue.
*
* <p> It is possible to create a phantom reference with a <tt>null</tt>
* queue, but such a reference is completely useless: Its <tt>get</tt>
* method will always return null and, since it does not have a queue, it
* will never be enqueued.
*
* @param referent the object the new phantom reference will refer to
* @param q the queue with which the reference is to be registered,
* or <tt>null</tt> if registration is not required
*/
public PhantomReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
}