Four reference types in Java
Micro-channel public number of rivers and lakes] [Java technology Java, a technical engineer Ali station. Author Huang oblique, focused Java related technologies: SSM, SpringBoot, MySQL, distributed, middleware, cluster, Linux, network, multi-threaded, occasionally speaking point Docker, ELK, as well as dry goods and technology to share the learning experience, committed to Java full stack development! (No reply after public concern "Java" Java can receive basic, advanced, and the project architect and other free learning materials, more databases, distributed, service and other popular micro learning video technology, rich content, both theory and practice, also presented will be the original author of the study guide Java, Java programmer interview guide and other dry goods resources)
One, background
Java's garbage collection does not require the programmer is responsible, JVM launches Java GC to complete garbage collection when necessary. Java so that we can control the life cycle of objects available to us four kinds of reference, citing strength from strong to weak are: strong references, soft references, weak references, phantom references.
Second, Introduction
1. strong references StrongReference
StrongReference Java is the default referral form, without explicitly defined use. Any object by strong reference used no matter how nervous system resources, Java GC will not take the initiative to reclaim objects that have strong references.
{class StrongReferenceTest public public static int M = 1024 * 1024; public static void printlnMemory (Tag String) { the Runtime Runtime = Runtime.getRuntime (); int = M StrongReferenceTest.M; System.out.println ( "\ n-" Tag + + ":"); System.out.println (Runtime.freeMemory () / M + "M (Free) /" + Runtime.totalMemory () / M + "M (Total)"); } public static void main (String [] args) { StrongReferenceTest.printlnMemory ( "original. 1 available memory and total memory."); // array 10M is instantiated and establishes strongReference strong references byte [] = strongReference new new byte [10 * StrongReferenceTest.M]; StrongReferenceTest.printlnMemory ( "instantiated 2. 10M array, and to establish a strong reference"); System.out.println ( "strongReference:" + strongReference); System.gc(); StrongReferenceTest.printlnMemory("3.GC后"); System.out.println("strongReference : "+strongReference); //strongReference = null;后,强引用断开了 strongReference = null; StrongReferenceTest.printlnMemory("4.强引用断开后"); System.out.println("strongReference : "+strongReference); System.gc(); StrongReferenceTest.printlnMemory("5.GC后"); System.out.println("strongReference : "+strongReference); } }
operation result:
2. Weak references WeakReference
If an object has only a weak reference, whether or not sufficient memory, Java GC after only a weak reference if the object will be automatically recovered.
public class WeakReferenceTest { public static int M = 1024*1024; public static void printlnMemory(String tag){ Runtime runtime = Runtime.getRuntime(); int M = WeakReferenceTest.M; System.out.println("\n"+tag+":"); System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)"); } public static void main(String[] args){ WeakReferenceTest.printlnMemory("1.原可用内存和总内存"); //创建弱引用 WeakReference<Object> weakRerference = new WeakReference<Object>(new byte[10*WeakReferenceTest.M]); WeakReferenceTest.printlnMemory("2.实例化10M的数组,并建立弱引用"); System.out.println("weakRerference.get() : "+weakRerference.get()); System.gc(); StrongReferenceTest.printlnMemory("3.GC后"); System.out.println("weakRerference.get() : "+weakRerference.get()); } }
运行结果:
3.软引用 SoftReference
软引用和弱引用的特性基本一致, 主要的区别在于软引用在内存不足时才会被回收。如果一个对象只具有软引用,Java GC在内存充足的时候不会回收它,内存不足时才会被回收。
public class SoftReferenceTest { public static int M = 1024*1024; public static void printlnMemory(String tag){ Runtime runtime = Runtime.getRuntime(); int M = StrongReferenceTest.M; System.out.println("\n"+tag+":"); System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)"); } public static void main(String[] args){ SoftReferenceTest.printlnMemory("1.原可用内存和总内存"); //建立软引用 SoftReference<Object> softRerference = new SoftReference<Object>(new byte[10*SoftReferenceTest.M]); SoftReferenceTest.printlnMemory("2.实例化10M的数组,并建立软引用"); System.out.println("softRerference.get() : "+softRerference.get()); System.gc(); SoftReferenceTest.printlnMemory("3.内存可用容量充足,GC后"); System.out.println("softRerference.get() : "+softRerference.get()); //实例化一个4M的数组,使内存不够用,并建立软引用 //free=10M=4M+10M-4M,证明内存可用量不足时,GC后byte[10*m]被回收 SoftReference<Object> softRerference2 = new SoftReference<Object>(new byte[4*SoftReferenceTest.M]); SoftReferenceTest.printlnMemory("4.实例化一个4M的数组后"); System.out.println("softRerference.get() : "+softRerference.get()); System.out.println("softRerference2.get() : "+softRerference2.get()); } }
运行结果:
4.虚引用 PhantomReference
从PhantomReference类的源代码可以知道,它的get()方法无论何时返回的都只会是null。所以单独使用虚引用时,没有什么意义,需要和引用队列ReferenceQueue类联合使用。当执行Java GC时如果一个对象只有虚引用,就会把这个对象加入到与之关联的ReferenceQueue中。
public class PhantomReferenceTest { public static int M = 1024*1024; public static void printlnMemory(String tag){ Runtime runtime = Runtime.getRuntime(); int M = PhantomReferenceTest.M; System.out.println("\n"+tag+":"); System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)"); } public static void main(String[] args) throws InterruptedException { PhantomReferenceTest.printlnMemory("1.原可用内存和总内存"); byte[] object = new byte[10*PhantomReferenceTest.M]; PhantomReferenceTest.printlnMemory("2.实例化10M的数组后"); //建立虚引用 ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>(); PhantomReference<Object> phantomReference = new PhantomReference<Object>(object,referenceQueue); PhantomReferenceTest.printlnMemory("3.建立虚引用后"); System.out.println("phantomReference : "+phantomReference); System.out.println("phantomReference.get() : "+phantomReference.get()); System.out.println("referenceQueue.poll() : "+referenceQueue.poll()); //断开byte[10*PhantomReferenceTest.M]的强引用 object = null; PhantomReferenceTest.printlnMemory("4.执行object = null;强引用断开后"); System.gc(); PhantomReferenceTest.printlnMemory("5.GC后"); System.out.println("phantomReference : "+phantomReference); System.out.println("phantomReference.get() : "+phantomReference.get()); System.out.println("referenceQueue.poll() : "+referenceQueue.poll()); //断开虚引用 phantomReference = null; System.gc(); PhantomReferenceTest.printlnMemory("6.断开虚引用后GC"); System.out.println("phantomReference : "+phantomReference); System.out.println("referenceQueue.poll() : "+referenceQueue.poll()); } }
运行结果:
三、小结
Java is a strong reference to the default referral form, do not need to show the use of definition, we usually use most often to the reference. No matter how tight the system resources, Java GC will not take the initiative to reclaim objects that have strong references. Weak references and soft references generally required when a non-object using reference object. The difference between them is weak reference object is always associated will be recycled when garbage collection, objects are associated soft reference will only be recovered at the lack of memory. Virtual referenced get () method to get is always null, unable to get the object instance. Java GC will virtual objects referenced by reference into the queue inside. It can be used to do some additional resources such as clean-up or things rollback process when the object is recovered. Since the lead can not be obtained from the virtual object to an instance of a reference. Its usage is rather special, it is not the virtual reference into this table for comparison. Here on strong references, weak references, soft references were compared:
Reference types | GC is sufficient JVM memory | GC when the JVM memory shortage |
---|---|---|
Strong references | Not recovered | Not recovered |
Weak references | Be recycled | Be recycled |
Soft references
|