目录强引用--不进行回收软引用--内存不足的时候进行回收弱引用--发现即回收虚引用--跟踪垃圾回收默认情况下通过System.gc()或者Runtime.getRuntime().gc()的调用会显示触发Full GC同时对老年代和年轻代进行回收。强引用--不进行回收使用 new 关键字创建出来的。软引用--内存不足的时候进行回收软引用是用来描述一些还有用但非必需的对象。只被软引用关联着的对象在系统将要发生内存溢出异常前会把这些对象列进回收范围之中进行第二次回收如果这次回收还没有足够的内存才会抛出内存溢出异常。软引用通常用来实现内存敏感的缓存。比如:高速缓存就有用到软引用。如果还有空闲内存就可以暂时保留缓存当内存不足时清理掉这样就保证了使用缓存的同时不会耗尽内存。垃圾回收器在某个时刻决定回收软可达的对象的时候会清理软引用并可选地把引用存放到一个引用队列(Reference Queue)。类似弱引用只不过Java虚拟机会尽量让软引用的存活时间长一些迫不得已才清理。通过SoftReference创建SoftReferenceUser softReference new SoftReferenceUser(new User(1,zhang_san)); System.gc(); System.out.println(GC之后打印\n softReference.get() softReference.get()); try { //让系统认为内存资源紧张、不够 byte[] b new byte[7168 * 1024]; } catch (Exception e) { throw new Exception(e); } finally { //再次从软引用中获取数据 System.out.println(创建了大对象之后重新获取 softReference.get() softReference.get()); }设置vm options参数如下-Xms10m -Xmx10m -XX:PrintGCDetails执行测试程序后出现oomgc之前打印 softReference.get() [id1, namezhang_san] GC之后打印 softReference.get() [id1, namezhang_san] 创建了大对象之后重新获取 softReference.get() null弱引用--发现即回收弱引用也是用来描述那些非必需对象只被弱引用关联的对象只能生存到下一次垃圾收集发生为止。在系统GC时只要发现弱引用不管系统堆空间使用是否充足都会回收掉只被弱引用关联的对象。由于垃圾回收器的线程通常优先级很低因此并不一定能很快地发现持有弱引用的对象。在这种情况下弱引用对象可以存在较长的时间。弱引用和软引用一样在构造弱引用时也可以指定一个引用队列当弱引用对象被回收时就会加入指定的引用队列通过这个队列可以跟踪对象的回收情况。弱引用非常适合来保存那些可有可无的缓存数据。如果这么做当系统内存不足时这些缓存数据会被回收不会导致内存溢出。而当内存资源充足时这些缓存数据又可以存在相当长的时间从而起到加速系统的作用。WeakReferenceUser weakReference new WeakReference(new User(1, li_si)); System.out.println( gc之前打印 weakReference.get()); System.gc(); System.out.println( gc 之后 weakReference.get());打印结果gc之前打印 [id1, nameli_si] gc 之后null补充python语言也有垃圾回收同时支持引用计数和垃圾收集机制。java没有使用引用计数算法存在难题--循环引用问题python使用了引用计数如何解决的手动解除在合适的时机解除引用关系使用弱引用weakref,weakref是Python提供的标准库旨在解决循环引用。虚引用--跟踪垃圾回收也称为幽灵引用或者幻影引用是所有引用类型中最弱的一个。一个对象是否有虚引用的存在完全不会决定对象的生命周期。如果一个对象仅持有虚引用那么它和没有引用几乎是一样的随时都可能被垃圾回收器回收。它不能单独使用也无法通过虚引用来获取被引用的对象。当试图通过虚引用的get()方法取得对象时总是null为一个对象设置虚引用关联的唯一目的在于跟踪垃圾回收过程比如:能在这个对象被收集器回收时收到一个系统通知。虚引用必须和引用队列一起使用。虚引用在创建时必须提供一个引用队列作为参数。当垃圾回收器准备回收一个对象时如果发现它还有虚引用就会在回收对象后将这个虚引用加入引用队列以通知应用程序对象的回收情况。由于虚引用可以跟踪对象的回收时间因此也可以将一些资源释放操作放置在虚引用中执行和记录。终结器引用(Final reference)它用以实现对象的finalize()方法也可以称为终结器引用。无需手动编码其内部配合引用队列使用。在GC时终结器引用入队。由Finalizer线程通过终结器引用找到被引用对象并调用它的finalize()方法第二次GC时才能回收被引用对象。#补充 finalize()#finalize的作用(1)finalize()与C中的析构函数不是对应的。C中的析构函数调用的时机是确定的(对象离开作用域或delete掉)但Java中的finalize的调用具有不确定性(2)不建议用finalize方法完成非内存资源的清理工作但建议用于:1清理本地对象(通过JNI创建的对象):2作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。#finalize的问题(1)一些与finalize相关的方法由于一些致命的缺陷已经被废弃了如System.runFinalizersOnExit()方法、Runtime.runFinalizersOnExit()方法(2)System.gc()与System.runFinalization()方法增加了finalize方法执行的机会但不可盲目依赖它们(3)]ava语言规范并不保证finalize方法会被及时地执行、而且根本不会保证它们会被执行(4)finalize方法可能会带来性能问题。因为JVM通常在单独的低优先级线程中完成finalize的执行(5)对象再生问题:finalize方法中可将待回收对象赋值给GC Roots可达的对象引用从而达到对象再生的目的(6)finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法但并不影响GC对finalize的行为)