《设计模式 单例模式讨论篇》由会员分享,可在线阅读,更多相关《设计模式 单例模式讨论篇(3页珍藏版)》请在金锄头文库上搜索。
1、设计模式 单例模式讨论篇单例模式讨论篇:单例模式与垃圾回收Jvm的垃圾回收机制到底会不会回收掉长时间不的单例模式对象,这的确是个 较有争议性的问题。将这部分内容单独成篇的的也是为了与博友泛的讨论 下这个问题。为了能让更多的看到这篇章,请各位博友看完章之后,点 下“顶“,让本篇章排名尽量的靠前。笔者在此谢过。讨论命题:当个单例的对象长久不时,会不会被jvm的垃圾收集机制回收。先说下为什么会产这疑问,笔者本再此之前从来没有考虑过垃圾回收对单 例模式的影响,直到去年读了本书,设计模式之禅秦波著。在书中提到在 j2ee应中,jvm垃圾回收机制会把长久不的单例类对象当作垃圾,并在cpu空闲的 时候对其进
2、回收。之前读过的本设计模式的书,包括java与模式,书中都没 有提到jvm垃圾回收机制对单例的影响。并且在作过程中,也没有过单例对象被回 收的经历,加上作中很多前辈曾经告诫过笔者:尽量不要声明太多的静态属性,因 为这些静态属性被加载后不会被释放。因此对jvm垃圾收集会回收单例对象这说法 持怀疑态度。渐渐地,发现在同事中和上的技术员中,对这问题也基本上是鲜 明的对两派。那么到底jvm会不会回收长久不的单例对象呢。对这问题,笔者本的观点是:不会回收。下给出本的测试代码class Singleton private byte a = new byte6*1024*1024;private stati
3、c Singleton singleton = new Singleton();private Singleton()public static Singleton getInstance()return singleton;class Obj private byte a = new byte3*1024*1024;public class Clientpublic static void main(String args) throws ExceptionSingleton.getInstance();while(true)new Obj();本段程序的的是模拟j2ee容器,先实例化单例类
4、,这个单例类占6M内存,然后程 序进死循环,不断的创建对象,逼迫jvm进垃圾回收,然后观察垃圾收集信息, 如果进垃圾收集后,内存仍然于6M,则说明垃圾回收不会回收单例对象。运本程序使的虚拟机是hotspot虚拟机,也就是我们使的最多的java官提供的 虚拟机,俗称jdk,版本是jdk1.6.0_12运时vm arguments参数为:-verbose:gc -Xms20M -Xmx20M,意思是每次jvm进垃 圾回收时显内存信息,jvm的内存设为固定20M。运结果:Full GC 18566K-6278K(20352K), 0.0101066 secs GC 18567K-18566K(203
5、52K), 0.0001978 secs Full GC 18566K-6278K(20352K), 0.0088229 secs从运结果中可以看到总有6M空间没有被收集。因此,笔者认为,少在hotspot虚拟 机中,垃圾回收是不会回收单例对象的。后来查阅了些相关的资料,hotspot虚拟机的垃圾收集算法使根搜索算法。这个算 法的基本思路是:对任何“活“的对象,定能最终追溯到其存活在堆栈或静态存储区 之中的引。通过系列名为根(GC Roots)的引作为起点,从这些根开始搜索, 经过系列的路径,如果可以到达java堆中的对象,那么这个对象就是“活“的,是不 可回收的。可以作为根的对象有:虚拟机栈
6、(栈桢中的本地变量表)中的引的对象。 法区中的类静态属性引的对象。 法区中的常量引的对象。 本地法栈中JNI的引的对象。法区是jvm的块内存区域,来存放类相关的信息。很明显,java中单例模式创建 的对象被类中的静态属性所引,符合第条,因此,单例对象不会被jvm垃圾 收集。虽然jvm堆中的单例对象不会被垃圾收集,但是单例类本如果长时间不会不会被 收集呢?因为jvm对法区也是有垃圾收集机制的。如果单例类被收集,那么堆中的 对象就会失去到根的路径,必然会被垃圾收集掉。对此,笔者查阅了hotspot虚拟机对 法区的垃圾收集法,jvm卸载类的判定条件如下:该类所有的实例都已经被回收,也就是java堆中
7、不存在该类的任何实例。 加载该类的ClassLoader已经被回收。 该类对应的java.lang.Class对象没有任何地被引,法在任何地通过反射 访问该类的法。只有三个条件都满,jvm才会在垃圾收集的时候卸载类。显然,单例的类不满条件,因此单例类也不会被卸载。也就是说,只要单例类中的静态引指向jvm堆中 的单例对象,那么单例类和单例对象都不会被垃圾收集,依据根搜索算法,对象是否 会被垃圾收集与未被使时间长短关,仅仅在于这个对象是不是“活“的。假如个 对象长久未使被回收,那么收集算法应该是最近最长未使算法,最近最长未使 算法般在操作系统的内外存交换中,如果在虚拟机垃圾回收中,岂不是太不 安全了?以上是笔者的观点。因此笔者的观点是:在hotspot虚拟机1.6版本中,除为地断开单例中静态引到 单例对象的联接,否则jvm垃圾收集器是不会回收单例对象的。参考献Java虚拟机规范Java hotspot虚拟机内存管理Java编程思想Java与模式设计模式设计模式之禅深理解java虚拟机W3Cschool()最的技术知识分享与学习平台此篇内容来于站户上传并发布。