zoukankan      html  css  js  c++  java
  • GC与幽灵引用 规格严格

    网上摘录一篇文章,来自http://qing.weibo.com/2095854040/7cec31d8330008rw.html内容如下,顺带自己体会:

     1、WeakReference/SoftReference,在GC时,如果这个Reference所引用的对象可以被回收,collector会首先将Reference.referent域直接清除(不通过调用clear()方法)。而后,才将Reference进行Enqueue操作,进入到构造时指定的ReferenceQueue中。

    2、所有Reference状态发生改变时,collector首先将这些对象全部加入到一个pending的链表中,然后通知Reference Handler线程进行处理,Reference Handler线程负责对pending链表中的每一个Reference进行ENQUEUE操作(有队列的)。

    3、Finalizer是一种特殊的Reference,很遗憾,在Java文档中没有正式提及。Finalizer在ENQUEUE之前是没有clear referent的,这使得Finalizer线程可以对referent对象调用finalize方法。在执行了finalize方法后,referent将被清除。由于这类对象的Finalizer引用实在构造时创建的,因此,执行了一次finalize方法后,这个Finalizer引用就被GC释放了,不会再次执行。

    4、如果一个对象,有finalize方法及WeakReference,那会是怎么样呢?有一个很奇怪的事情可能会发生:那就是GC时,WeakReference会clear掉,而后Finalizer会ENQUEUE、执行finalize方法。如果在finalize方法中让对象恢复强引用,那么,很不幸的事情发生:这个WeakReference已经不再真实反映了,实际的对象没有GC掉,但WeakReference已经被清除了。(应该说,我不认为这是JVM Spec的Bug) 今天遇到一个非常奇怪的现象,在Solaris上的JDK1.6,居然在运行时出现了很多的Finalizer对象,却没有及时的被GC掉,而且Full GC也没有将这些对象GC掉(这些对象已经不再存在其他的root-reference)。当然,在一个更晚的时间点,这些对象是已经被GC掉了。从 heap的分析来看,collector是实际上已经将这些对象挂接到了reference pending链 表中,可惜的是,却没有进行notify操作,使得这些本来应该提早就进行回收的对象不断的延迟。不太清楚这是不是Solaris上的JVM的一个 Bug,反正对我们系统的性能来说,是有一定的影响的,导致了GC效率是存在一定程度上的降低。在Linux上没有发现这个问题。  

    对于1,如果是PhantomReference应该也是适用的。

    对于2,可以参照Reference中的代码看,pending列表按照代码说明,确实是垃圾回收器干的

    对于3,很诡异,因为Finalizer在我运行的demo看,同时存在PhantomReference情况下,先是做Finalize行为,然后才是PhantomReference,这里面确实如上文所说的,Finalizer是特殊的Reference,并且也有ENQUEUE的行为,但是很奇怪,难道存在多个Reference下,也是有优先级的么?

    对于4,我也遇见过,但是WeakReference应该一般清除不了吧,除非认为设置NULL。

    结论,总之,这块涉及到垃圾回收和JVM内部行为,研究起来还是很有趣的一件事情,那位仁兄又更好的链接和知识可以教我一下。

  • 相关阅读:
    [转]tomcat启动报错too low setting for -Xss
    linux(centos) tomcat设置开机启动
    docker--centos镜像安装tomcat jdk1.8 mysql部署java web项目
    docker--常用命令
    docker--容器和镜像的导入导出及部署
    docker--在centos镜像安装mysql
    docker--(MAC ubuntu centos)安装
    js常用判断和语法
    linux命令-crontab
    ajax的另一种成功和失败回调函数
  • 原文地址:https://www.cnblogs.com/diyunpeng/p/2658798.html
Copyright © 2011-2022 走看看