深入了解JAVA技术(4)对象怎么死亡?

垃圾收集器

你觉得对象死了吗?

大家都知道JAVA堆里面存放整个项目中几乎所有的对象实例上,垃圾收集器在对堆进行回收前,都做了哪些呢?哪些还活着,哪些已经死了
引用计数算法
很多认为对象是否存在的算法是这样的:给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1;当引用失效时,计数器值就减1;无论什么时刻计数器为0的对象就不能再被使用.
可达性分析算法
在主流的商用程序语言(Java,C#),都是通过可达性分析来判定对象是否存活的,基本思路是通过“GC Roots”对象作为起始点,从这些节点开始向下搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则说明这个对象不可用,垃圾收集器判定可回收对象,如图
在这里插入图片描述
GC Roots对象包括虚拟机栈中引用的对象,方法区中类静态属性引用的对象,方法区中常量引用的对象,本地方法引用的对象
到底对象生存还是死亡
在可达性分析算法中不可达的对象,不一定是绝对死亡,在这种时候它们暂时要至少经历两次标记过程。如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那么将对对象进行第一次标记并进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法,当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机认为都不需要执行。如果这个对象有覆盖finalize()方法,同时认为这个对象有必要执行finalize()方法,那这个对象就会被放置在F-queue队列中,并等一下由虚拟机自动建立一条低优先级的finalizer线程去执行它。刚才提到的执行虚拟机只会触法这个方法,但不承诺会等待他运行结束,原因是,如果这个对象在finalize()方法中执行缓慢,或者发生了死循环,严重会导致整个内存回收系统崩溃。所以执行finalize()方法有可能失败,对象没有被摧毁。
回收方法区
有些人日为方法区是没有垃圾收集的,Java虚拟机确实也没有要求在方法区实现垃圾收集,而且在方法区中进行垃圾收集的“性价比”特别低,在堆中,特别是在新生代中,正常进行一次垃圾收集一般可以回收宝7成到9成的空间,而方法区垃圾收集效率远低于此。
方法区的垃圾收集主要回收两部分内容:废弃常量和无用的类。回收废弃常量与回收Java堆中的常量相似,假如常量池中的“abc”字符串没有任何一个spring对象引用他,也没有在其他地方引用过他,如果这时发生内存回收的,这个“abc”字符串就有必要清理出常量池。那么怎样判定一个类是否无用?
判定无用的类需要满足3个条件

  1. Java堆中不存在该类的任何实例
  2. 加载该类的class loader 已经被回收
  3. 该类的对应的Java.lang.class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
    这里处理无用的类并不是和对象一样,不使用了就必然会回收.是否对类进行回收,例如hotspot虚拟机也提供了-Xnoclassgc参数进行控制,也可以使用-verbose:class以及-XX:+TraceClassLoading,-XX:+TraceClassUnLoading查看类加载和卸载信息.
    在大量使用反射,动态代理,CGLib等ByteCode框架,动态生成JSP以及OSGi这类频繁自定义classloader的场景都需要虚拟机具备卸载类的功能,才能保证永久代不会溢出
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听不见你的名字

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值