单例模式垃圾回收_动力节点Java学院整理

 更新时间:2017年08月08日 10:18:14   作者:zhengzhb  
这篇文章主要为大家详细介绍了单例模式垃圾回收的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

讨论命题:当一个单例的对象长久不用时,会不会被jvm的垃圾收集机制回收。

        首先说一下为什么会产生这一疑问,笔者本人再此之前从来没有考虑过垃圾回收对单例模式的影响,直到去年读了一本书,《设计模式之禅》秦小波著。在书中提到在j2ee应用中,jvm垃圾回收机制会把长久不用的单例类对象当作垃圾,并在cpu空闲的时候对其进行回收。之前读过的几本设计模式的书,包括《Java与模式》,书中都没有提到jvm垃圾回收机制对单例的影响。并且在工作过程中,也没有过单例对象被回收的经历,加上工作中很多前辈曾经告诫过笔者:尽量不要声明太多的静态属性,因为这些静态属性被加载后不会被释放。因此对jvm垃圾收集会回收单例对象这一说法持怀疑态度。渐渐地,发现在同事中和网上的技术人员中,对这一问题也基本上是鲜明的对立两派。那么到底jvm会不会回收长久不用的单例对象呢。

        对这一问题,笔者本人的观点是:不会回收

下面给出本人的测试代码

class Singleton {
 private byte[] a = new byte[6*1024*1024];
 private static Singleton singleton = new Singleton();
 private Singleton(){}
 
 public static Singleton getInstance(){
 return singleton;
 }
}

class Obj {
 private byte[] a = new byte[3*1024*1024];
}

public class Client{
 public static void main(String[] args) throws Exception{
 Singleton.getInstance();
 while(true){
  new Obj();
 }
 }
}


        本段程序的目的是模拟j2ee容器,首先实例化单例类,这个单例类占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(20352K), 0.0001978 secs]
[Full GC 18566K->6278K(20352K), 0.0088229 secs]
……

        从运行结果中可以看到总有6M空间没有被收集。因此,笔者认为,至少在hotspot虚拟机中,垃圾回收是不会回收单例对象的。

        后来查阅了一些相关的资料,hotspot虚拟机的垃圾收集算法使用根搜索算法。这个算法的基本思路是:对任何“活”的对象,一定能最终追溯到其存活在堆栈或静态存储区之中的引用。通过一系列名为根(GC Roots)的引用作为起点,从这些根开始搜索,经过一系列的路径,如果可以到达java堆中的对象,那么这个对象就是“活”的,是不可回收的。可以作为根的对象有:

  • 虚拟机栈(栈桢中的本地变量表)中的引用的对象。
  • 方法区中的类静态属性引用的对象。
  • 方法区中的常量引用的对象。
  • 本地方法栈中JNI的引用的对象。

        方法区是jvm的一块内存区域,用来存放类相关的信息。很明显,java中单例模式创建的对象被自己类中的静态属性所引用,符合第二条,因此,单例对象不会被jvm垃圾收集。

        虽然jvm堆中的单例对象不会被垃圾收集,但是单例类本身如果长时间不用会不会被收集呢?因为jvm对方法区也是有垃圾收集机制的。如果单例类被收集,那么堆中的对象就会失去到根的路径,必然会被垃圾收集掉。对此,笔者查阅了hotspot虚拟机对方法区的垃圾收集方法,jvm卸载类的判定条件如下:

  • 该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
  • 加载该类的ClassLoader已经被回收。
  • 该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。

        只有三个条件都满足,jvm才会在垃圾收集的时候卸载类。显然,单例的类不满足条件一,因此单例类也不会被卸载。也就是说,只要单例类中的静态引用指向jvm堆中的单例对象,那么单例类和单例对象都不会被垃圾收集,依据根搜索算法,对象是否会被垃圾收集与未被使用时间长短无关,仅仅在于这个对象是不是“活”的。假如一个对象长久未使用而被回收,那么收集算法应该是最近最长未使用算法,最近最长未使用算法一般用在操作系统的内外存交换中,如果用在虚拟机垃圾回收中,岂不是太不安全了?以上是笔者的观点。

        因此笔者的观点是:在hotspot虚拟机1.6版本中,除非人为地断开单例中静态引用到单例对象的联接,否则jvm垃圾收集器是不会回收单例对象的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Springboot+redis+Interceptor+自定义annotation实现接口自动幂等

    Springboot+redis+Interceptor+自定义annotation实现接口自动幂等

    本篇文章给大家介绍了使用springboot和拦截器、redis来优雅的实现接口幂等,对于幂等在实际的开发过程中是十分重要的,因为一个接口可能会被无数的客户端调用,如何保证其不影响后台的业务处理,如何保证其只影响数据一次是非常重要的,感兴趣的朋友跟随小编一起看看吧
    2019-07-07
  • 一小时迅速入门Mybatis之增删查改篇

    一小时迅速入门Mybatis之增删查改篇

    这篇文章主要介绍了迅速入门Mybatis之增删查改篇,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • java中类之间的数据传递方式

    java中类之间的数据传递方式

    这篇文章主要介绍了java中类之间的数据传递方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 实例讲解spring boot 多线程

    实例讲解spring boot 多线程

    这篇文章主要介绍了spring boot 多线程的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • Java 图片压缩实现思路及代码

    Java 图片压缩实现思路及代码

    本文为大家详细介绍下图片压缩的具体实现思路及java代码,想学习的各位可以参考下哈,希望对大家有所帮助
    2013-07-07
  • Java大数运算BigInteger与进制转换详解

    Java大数运算BigInteger与进制转换详解

    这篇文章主要介绍了Java大数运算BigInteger与进制转换详解,Java 提供了 BigInteger(大整数)类和 BigDecimal(大浮点数)类用于大数运算,这两个类都继承自 Number 类(抽象类),由于 BigInteger 在大数运算中更常见,需要的朋友可以参考下
    2023-09-09
  • SpringSecurity实现动态加载权限信息的方法

    SpringSecurity实现动态加载权限信息的方法

    这篇文章主要介绍了SpringSecurity实现动态加载权限信息,本文给大家介绍的非常详细,对大家的学习或工作具有一定需要的朋友可以参考下
    2022-01-01
  • IDEA下SpringBoot指定环境、配置文件启动操作过程

    IDEA下SpringBoot指定环境、配置文件启动操作过程

    这篇文章主要介绍了IDEA下SpringBoot指定环境、配置文件启动过程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • Java实现接月饼小游戏的示例代码

    Java实现接月饼小游戏的示例代码

    本文将用Java语言自制一个小游戏:《接月饼小游戏》,游戏规则为不要被月亮砸到,尽可能地多接月饼。文中的实现代码讲解清晰,感兴趣的可以动手试一试
    2022-02-02
  • idea编写yml、yaml文件以及其优先级的使用

    idea编写yml、yaml文件以及其优先级的使用

    本文主要介绍了idea编写yml、yaml文件以及其优先级的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07

最新评论