01 PhantomReference没有进入ReferenceQueue
前言
最近 看到一篇文章, 然后 基于改文章的代码, 做了一些 调整, 然后 发现了一些 奇怪的事情, 并稍微整理了一下 原因
该文章地址 : https://hllvm-group.iteye.com/group/topic/34934
测试代码如下 :
package com.hx.test02;import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;/*** Test02WeakReferenceAfterGc** @author Jerry.X.He <970655147@qq.com>* @version 1.0* @date 2019-10-14 11:23*/
public class Test02WeakReferenceAfterGc {// Test02WeakReferenceAfterGc// refer : https://hllvm-group.iteye.com/group/topic/34934public static void main(String[] args) throws Exception {ReferenceQueue<Obj> referenceQueue = new ReferenceQueue<>();for (int i = 0; i < 1; i++) {Obj o = new Obj("object_" + i);
// SoftReference<Obj> ref = new SoftReference<>(o, referenceQueue);
// WeakReference<Obj> ref = new WeakReference<>(o, referenceQueue);PhantomReference<Obj> ref = new PhantomReference<>(o, referenceQueue);o = null;System.gc();Field field = Reference.class.getDeclaredField("referent");field.setAccessible(true);System.out.println(field.get(ref));}// 这个现象, 有 finalize 和 没有 finalize 是两个不同的情况, 按照理论上来说[常规的思考], 有 finalize 的情况下, 应该会有两个 Reference 分别进入 两个队列, 但是没有Thread.sleep(3000);System.gc();// consumernew Thread() {public void run() {while (true) {Object o = referenceQueue.poll();if (o != null) {try {Field rereferent = Reference.class.getDeclaredField("referent");rereferent.setAccessible(true);Object result = rereferent.get(o);System.out.println("gc will collect : " + o.getClass() + "@" + o.hashCode() + ", referent : " + result);} catch (Exception e) {e.printStackTrace();}}}}}.start();}/*** Obj** @author Jerry.X.He <970655147@qq.com>* @version 1.0* @date 2019-10-14 11:24*/static class Obj {private final String name;Obj(String name) {this.name=name;}// test for FinalReference
// @Override
// protected void finalize() throws Throwable {
// System.out.println("执行finalize方法:" + name);
// super.finalize();
// }@Overridepublic String toString() {return name;}}}
然后 我们这里 需要关注的主要的问题在于, Test02WeakReferenceAfterGc$Obj 在没有重写 finalize 方法的时候, 输出如下
object_0
gc will collect : class java.lang.ref.PhantomReference@1964850888, referent : object_0
在 Test02WeakReferenceAfterGc$Obj 重写了 finalize 方法之后 输出如下
object_0
执行finalize方法:object_0
这里 直观感觉就很奇怪了呀, 为什么 是否重写 finalize 方法, 会影响到 PhantomReference 进入对应的 引用队列呢 ?
针对重写 finalize 方法的情况讨论
最开始 我以为是 第一个 System.gc 之后, Obj 的实例 o 对应的 FinalReferece 会引用该对象, 所以该 对象在gc的时候没有被清理, 所以 该 PhantomReference 没有被整理, 然后 上面的这段代码, 是我为了这个猜想增加的
Thread.sleep(3000);System.gc();
但是, 发现 给定的 PhantomReference 还是没有 进入对应的引用队列
这个就很令人 疑惑了
测试代码均在jdk8下面编译, 以上测试代码结果, 运行于 jdk8, 一下部分代码, 截图基于 openjdk9
在 openjdk9 下面运行该测试方法, ref.get() 均为 null, 后面会提及到这一点的原因
以下描述 仅仅会描述一些和我们这里相关的部分, 整体的其他逻辑不会做过多描述
以下调试的参数为
-da -dsa -Xint -XX:+UseSerialGC com.hx.test02.Test02WeakReferenceAfterGc
以下调试的基于 openjdk9, 并且有一部分个人方便调试的调整, 调整的部分为
jvm.cpp
JVM_ENTRY_NO_ENV(void, JVM_GC(void))JVMWrapper("JVM_GC");if (!DisableExplicitGC) {
- Universe::heap()->collect(GCCause::_java_lang_system_gc);
+ VM_GenCollectForAllocation op(100, true, Universe::heap()->total_collections());
+ VMThread::execute(&op);}
JVM_END
System.gc 调整成为 ygc, 所以 可能和我们直接使用 jdk 运行的运行时情况稍有不一致的地方, 所以本文的调试 可能会存在一些局限
另外 由于本人水平有限, 理解能力有限有限, 可能也会导致一些问题的存在
问题的细节
1. 相关代码片段
首先先贴一下一部分关键代码, 在gc处理的过程中 会进行引用处理, 这里的 _discoveredXXRefs 来自于 复制算法遍历活跃对象的时候额外的针对 Reference 对象做了一些 Discover[参见instanceRefKlass.inline.oop_oop_iterate]
ReferenceProcessor::process_discovered_references
ReferenceProcessorStats ReferenceProcessor::process_discovered_references(BoolObjectClosure* is_alive,OopClosure* keep_alive,VoidClosure* complete_gc,AbstractRefProcTaskExecutor* task_executor,GCTimer* gc_timer) {assert(!enqueuing_is_done(), "If here enqueuing should not be complete");// Stop treating discovered references specially.disable_discovery();// If discovery was concurrent, someone could have modified// the value of the static field in the j.l.r.SoftReference// class that holds the soft reference timestamp clock using// reflection or Unsafe between when discovery was enabled and// now. Unconditionally update the static field in ReferenceProcessor// here so that we use the new value during processing of the// discovered soft refs._soft_ref_timestamp_clock = java_lang_ref_SoftReference::clock();ReferenceProcessorStats stats(total_count(_discoveredSoftRefs),total_count(_discoveredWeakRefs),total_count(_discoveredFinalRefs),total_count(_discoveredPhantomRefs));// Soft references{GCTraceTime(Debug, gc, ref) tt("SoftReference", gc_timer);process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,is_alive, keep_alive, complete_gc, task_executor);}update_soft_ref_master_clock();// Weak references{GCTraceTime(Debug, gc, ref) tt("WeakReference", gc_timer);process_discovered_reflist(_discoveredWeakRefs, NULL, true,is_alive, keep_alive, complete_gc, task_executor);}// Final references{GCTraceTime(Debug, gc, ref) tt("FinalReference", gc_timer);process_discovered_reflist(_discoveredFinalRefs, NULL, false,is_alive, keep_alive, complete_gc, task_executor);}// Phantom references{GCTraceTime(Debug, gc, ref) tt("PhantomReference", gc_timer);process_discovered_reflist(_discoveredPhantomRefs, NULL, true,is_alive, keep_alive, complete_gc, task_executor);}// Weak global JNI references. It would make more sense (semantically) to// traverse these simultaneously with the regular weak references above, but// that is not how the JDK1.2 specification is. See #4126360. Native code can// thus use JNI weak references to circumvent the phantom references and// resurrect a "post-mortem" object.{GCTraceTime(Debug, gc, ref) tt("JNI Weak Reference", gc_timer);if (task_executor != NULL) {task_executor->set_single_threaded_mode();}process_phaseJNI(is_alive, keep_alive, complete_gc);}log_debug(gc, ref)("Ref Counts: Soft: " SIZE_FORMAT " Weak: " SIZE_FORMAT " Final: " SIZE_FORMAT " Phantom: " SIZE_FORMAT,stats.soft_count(), stats.weak_count(), stats.final_count(), stats.phantom_count());log_develop_trace(gc, ref)("JNI Weak Reference count: " SIZE_FORMAT, count_jni_refs());return stats;
}
ReferenceProcessor::process_discovered_reflist
void ReferenceProcessor::process_discovered_reflist(DiscoveredList refs_lists[],ReferencePolicy* policy,bool clear_referent,BoolObjectClosure* is_alive,OopClosure* keep_alive,VoidClosure* complete_gc,AbstractRefProcTaskExecutor* task_executor)
{bool mt_processing = task_executor != NULL && _processing_is_mt;// If discovery used MT and a dynamic number of GC threads, then// the queues must be balanced for correctness if fewer than the// maximum number of queues were used. The number of queue used// during discovery may be different than the number to be used// for processing so don't depend of _num_q < _max_num_q as part// of the test.bool must_balance = _discovery_is_mt;if ((mt_processing && ParallelRefProcBalancingEnabled) ||must_balance) {balance_queues(refs_lists);}// Phase 1 (soft refs only):// . Traverse the list and remove any SoftReferences whose// referents are not alive, but that should be kept alive for// policy reasons. Keep alive the transitive closure of all// such referents.if (policy != NULL) {if (mt_processing) {RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);task_executor->execute(phase1);} else {for (uint i = 0; i < _max_num_q; i++) {process_phase1(refs_lists[i], policy,is_alive, keep_alive, complete_gc);}}} else { // policy == NULLassert(refs_lists != _discoveredSoftRefs,"Policy must be specified for soft references.");}// Phase 2:// . Traverse the list and remove any refs whose referents are alive.if (mt_processing) {RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);task_executor->execute(phase2);} else {for (uint i = 0; i < _max_num_q; i++) {process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);}}// Phase 3:// . Traverse the list and process referents as appropriate.if (mt_processing) {RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);task_executor->execute(phase3);} else {for (uint i = 0; i < _max_num_q; i++) {process_phase3(refs_lists[i], clear_referent,is_alive, keep_alive, complete_gc);}}
}
process_phase1 : 主要是 SoftReference 的处理[只有SoftReference传入了 policy], 根据 referencePolicy 来校验当前 Reference 是否应该移出 discoverList
process_phase2 : 如果 referent 经过了 ygc 还存活着, 那么 将当前 Reference 移出 discoverList
process_phase3 : 如果需要 clear_referent, 则清理掉 Reference.referent, 否则 将Reference.referent移动到 存活对象区域 [仅仅FinalReference传入为false, FinalReference业务处理的时候还需要referent]
ReferenceProcessor::process_phase3
// Traverse the list and process the referents, by either
// clearing them or keeping them (and their reachable
// closure) alive.
void
ReferenceProcessor::process_phase3(DiscoveredList& refs_list,bool clear_referent,BoolObjectClosure* is_alive,OopClosure* keep_alive,VoidClosure* complete_gc) {ResourceMark rm;DiscoveredListIterator iter(refs_list, keep_alive, is_alive);while (iter.has_next()) {iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */));if (clear_referent) {// NULL out referent pointeriter.clear_referent();} else {// keep the referent arounditer.make_referent_alive();}log_develop_trace(gc, ref)("Adding %sreference (" INTPTR_FORMAT ": %s) as pending",clear_referent ? "cleared " : "", p2i(iter.obj()), iter.obj()->klass()->internal_name());assert(iter.obj()->is_oop(UseConcMarkSweepGC), "Adding a bad reference");iter.next();}// Close the reachable setcomplete_gc->do_void();
}
经过 ReferenceProcessor::process_discovered_references 处理之后, 最后 还存在于 discoverList 的 Reference 与 Reference.pending 关联 [gc处理之后, genCollectedHeap.collect_generation里面 rp->enqueue_discovered_references]
然后 ReferenceHandler 线程会进行下一个阶段的处理, 将 Reference.pending 关联的列表的 所有的 Reference 关联到 Reference 对应的队列[参见 Reference$ReferenceHandler]
2. Test02WeakReferenceAfterGc$Obj 没有重写 finalize
首先我们来看一下 Test02WeakReferenceAfterGc$Obj 没有重写 finalize 方法的场景
三个断点, thread.create_vm 方法末尾一个, defNewGeneration.collect 里面 ref_processor.process_discovered_references 一个, referenceProcessor.process_discovered_references 里面 process_discovered_reflist(_discoveredPhantomRefs 一个
当断点停留在 "referenceProcessor.process_discovered_references" 里面的时候
2.1 确定当前位置
找到 main 线程, 打印 main 线程的 stackTrace, 从这里 可以知道 目前是 在 第一个 System.gc 方法的执行期间
$jerry : thread->print()
"main" #1 prio=5 os_prio=31 tid=0x00007fa786803800 nid=0x2403 waiting on condition [0x0000700007756000]java.lang.Thread.State: RUNNABLEJavaThread state: _thread_blocked
Thread: 0x00007fa786803800 [0x2403] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0$jerry : thread->print_stack()JavaThread state: _thread_blockedat java.lang.Runtime.gc(java.base/Native Method)at java.lang.System.gc(java.base/System.java:1726)at com.hx.test02.Test02WeakReferenceAfterGc.main(Test02WeakReferenceAfterGc.java:27)
2.2 process_discovered_reflist(_discoveredPhantomRefs 处理之前
然后我们回到 gc 线程, 在断点处 执行如下脚本, 打印探测到的 PhantomReference 列表
oop current = ((_discoveredPhantomRefs)->head());
for(int i=0; i<_discoveredPhantomRefs->length(); i++) {// tty->print_cr(current->klass()->external_name());current.print();current = java_lang_ref_Reference::discovered(current);
}
得到结果如下
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x000000074275dcd0} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x00000007404034b0} (e8080696 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84ebb91)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074275dc88} (e84ebb91 e84eaf9e)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742757cf0} (e84eaf9e e84ebb91)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074275dc88} (e84ebb91 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84ec6c6)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x0000000742763630} (e84ec6c6 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x000000074275dc88} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x000000074036f6a0} (e806ded4 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84eaf9e)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742757cf0} (e84eaf9e e84ebb9a)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074275dcd0} (e84ebb9a e84eaf95)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742757ca8} (e84eaf95 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84ec6c3)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x0000000742763618} (e84ec6c3 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x0000000742757cf0} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740409798} (e80812f3 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84eaf95)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742757ca8} (e84eaf95 e84ea6b5)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007427535a8} (e84ea6b5 e84ebb9a)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074275dcd0} (e84ebb9a e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84ebba0)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x000000074275dd00} (e84ebba0 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x0000000742757ca8} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x000000074036d7f8} (e806daff e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84ea6b5)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007427535a8} (e84ea6b5 e84ebb91)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074275dc88} (e84ebb91 e84ea6ac)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742753560} (e84ea6ac e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84ebb97)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x000000074275dcb8} (e84ebb97 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x00000007427535a8} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740410730} (e80820e6 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84ea6ac)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742753560} (e84ea6ac e84e9c27)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074274e138} (e84e9c27 e84eaf9e)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742757cf0} (e84eaf9e e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84eafa4)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x0000000742757d20} (e84eafa4 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x0000000742753560} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x000000074036a828} (e806d505 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e9c27)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074274e138} (e84e9c27 e84eaf95)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742757ca8} (e84eaf95 e84e9c1e)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074274e0f0} (e84e9c1e e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84eaf9b)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x0000000742757cd8} (e84eaf9b 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x000000074274e138} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x00000007404242d0} (e808485a e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e9c1e)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074274e0f0} (e84e9c1e e84e8c52)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742746290} (e84e8c52 e84ea6b5)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007427535a8} (e84ea6b5 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84ea6bb)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x00000007427535d8} (e84ea6bb 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x000000074274e0f0} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740359488} (e806b291 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e8c52)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742746290} (e84e8c52 e84ea6ac)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742753560} (e84ea6ac e84e8c49)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742746248} (e84e8c49 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84ea6b2)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x0000000742753590} (e84ea6b2 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x0000000742746290} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740431a28} (e8086345 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e8c49)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742746248} (e84e8c49 e84e77b7)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074273bdb8} (e84e77b7 e84e9c27)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074274e138} (e84e9c27 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e9c2d)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x000000074274e168} (e84e9c2d 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x0000000742746248} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740351e60} (e806a3cc e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e77b7)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074273bdb8} (e84e77b7 e84e9c1e)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074274e0f0} (e84e9c1e e84e77ae)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074273bd70} (e84e77ae e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e9c24)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x000000074274e120} (e84e9c24 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x000000074273bdb8} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740438e00} (e80871c0 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e77ae)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074273bd70} (e84e77ae e84e571d)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074272b8e8} (e84e571d e84e8c52)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742746290} (e84e8c52 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e8c58)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x00000007427462c0} (e84e8c58 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x000000074273bd70} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x000000074019cef8} (e80339df e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e571d)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074272b8e8} (e84e571d e84e8c49)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742746248} (e84e8c49 e84e5714)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074272b8a0} (e84e5714 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e8c4f)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x0000000742746278} (e84e8c4f 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x000000074272b8e8} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740445580} (e8088ab0 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e5714)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074272b8a0} (e84e5714 e84e2db8)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742716dc0} (e84e2db8 e84e77b7)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074273bdb8} (e84e77b7 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e77bd)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x000000074273bde8} (e84e77bd 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x000000074272b8a0} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740193d48} (e80327a9 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e2db8)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742716dc0} (e84e2db8 e84e77ae)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074273bd70} (e84e77ae e84e2daf)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742716d78} (e84e2daf e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e77b4)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x000000074273bda0} (e84e77b4 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x0000000742716dc0} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740449470} (e808928e e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84e2daf)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742716d78} (e84e2daf e84de643)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426f3218} (e84de643 e84e571d)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074272b8e8} (e84e571d e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e5723)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x000000074272b918} (e84e5723 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x0000000742716d78} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740188140} (e8031028 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84de643)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426f3218} (e84de643 e84e5714)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x000000074272b8a0} (e84e5714 e84de63a)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426f31d0} (e84de63a e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e571a)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x000000074272b8d0} (e84e571a 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x00000007426f3218} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x000000074044c550} (e80898aa e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84de63a)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426f31d0} (e84de63a e84da7f7)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426d3fb8} (e84da7f7 e84e2db8)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742716dc0} (e84e2db8 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e2dbe)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x0000000742716df0} (e84e2dbe 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x00000007426f31d0} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x0000000740172188} (e802e431 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84da7f7)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426d3fb8} (e84da7f7 e84e2daf)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742716d78} (e84e2daf e84da7f1)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426d3f88} (e84da7f1 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84e2db5)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x0000000742716da8} (e84e2db5 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x00000007426d3fb8} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x000000074044ed28} (e8089da5 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84da7f1)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426d3f88} (e84da7f1 e84d6a6d)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426b5368} (e84d6a6d e84de643)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426f3218} (e84de643 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84de649)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x00000007426f3248} (e84de649 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x00000007426d3f88} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'sun/nio/fs/NativeBuffer'{0x0000000740036f20} (e8006de4 e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d6a6d)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426b5368} (e84d6a6d e84de63a)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426f31d0} (e84de63a e84d6a68)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$CleanerCleanable'{0x00000007426b5340} (e84d6a68 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84de640)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'sun/nio/fs/NativeBuffer$Deallocator'{0x00000007426f3200} (e84de640 0)
jdk.internal.ref.CleanerImpl$PhantomCleanableRef
{0x00000007426b5368} - klass: 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'- ---- fields (total size 6 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/invoke/ConstantCallSite'{0x000000074045dfe8} (e808bbfd e84d06ce)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683670} (e84d06ce 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d2df2)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'jdk/internal/ref/Cleaner'{0x0000000742696f90} (e84d2df2 e84d2fe6)- strict 'prev' 'Ljdk/internal/ref/PhantomCleanable;' @28 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84da7f7)- strict 'next' 'Ljdk/internal/ref/PhantomCleanable;' @32 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x00000007426d3fb8} (e84da7f7 e84d2fe6)- private final strict 'list' 'Ljdk/internal/ref/PhantomCleanable;' @36 a 'jdk/internal/ref/CleanerImpl$PhantomCleanableRef'{0x0000000742697f30} (e84d2fe6 e84da7fd)- private final 'action' 'Ljava/lang/Runnable;' @40 a 'java/lang/invoke/MethodHandleNatives$CallSiteContext'{0x00000007426d3fe8} (e84da7fd 0)
jdk.internal.ref.Cleaner
{0x0000000742696f90} - klass: 'jdk/internal/ref/Cleaner'- ---- fields (total size 5 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/nio/DirectByteBuffer'{0x0000000740189c90} (e8031392 e84d2dee)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742696f70} (e84d2dee 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d0774)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/PhantomReference'{0x0000000742683ba0} (e84d0774 0)- private 'next' 'Ljdk/internal/ref/Cleaner;' @28 NULL (0 0)- private 'prev' 'Ljdk/internal/ref/Cleaner;' @32 NULL (0 e84d60c1)- private final 'thunk' 'Ljava/lang/Runnable;' @36 a 'java/nio/DirectByteBuffer$Deallocator'{0x00000007426b0608} (e84d60c1 9)
java.lang.ref.PhantomReference
{0x0000000742683ba0} - klass: 'java/lang/ref/PhantomReference'- ---- fields (total size 4 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'com/hx/test02/Test02WeakReferenceAfterGc$Obj'{0x00000007404e1df0} (e809c3be e84d0770)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683b80} (e84d0770 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d0774)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/PhantomReference'{0x0000000742683ba0} (e84d0774 0)
这里面的内容很多, 但是实际上我们只用关心 最后一个 "private strict 'referent' 'Ljava/lang/Object;' @12 a 'com/hx/test02/Test02WeakReferenceAfterGc$Obj'{0x00000007404e1df0} (e809c3be e84d0770)"
在之后的截图, 可能我这边会 去掉 部分与本主题无关的的引用的信息, 方便查看 , 并且都会加上备注
可以发现 gc 的时候找到了 我们的这个 “ref” 引用, 然后 这里是待处理的状态, 那么会怎么处理呢 ?
1.3 process_discovered_reflist(_discoveredPhantomRefs 处理之后
然后 断点下走一步, 我们再来看一下 _discoveredPhantomRefs 列表的数据
同样执行 上面查看 _discoveredPhantomRefs 列表的代码片, 得到如下结果
## 省略掉部分无关的 CleanerImpl$PhantomCleanableRef, Cleaner
java.lang.ref.PhantomReference
{0x0000000742683ba0} - klass: 'java/lang/ref/PhantomReference'- ---- fields (total size 4 words):- private strict 'referent' 'Ljava/lang/Object;' @12 NULL (0 e84d0770)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683b80} (e84d0770 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d0774)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/PhantomReference'{0x0000000742683ba0} (e84d0774 0)
根据上面的 oop 的地址 0x0000000742683ba0 可以定位到上面的 PhantomReference 就是 "process_discovered_reflist(_discoveredPhantomRefs" 处理之后的数据了
可以发现 变化在于 referent 被置为 NULL 了
tips : 但是 在openjdk8对于 PhantomReference 的 process_phase3的处理是不会将 referent 置为 NULL 的, 参见 : http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/memory/referenceProcessor.cpp 249-252行
这个是由于 process_phase3 的过程中发现 referent 已经 gg 了, 然后就清理掉了 ref.referent 然后并且把它留在了 discoverList, 等待后续的步骤进行处理
然后后续 vm 将还存在的 discoverList 的引用关联到 Reference.pending 的列表上面
ReferenceHandler 将 Reference.pending 列表上的 Reference 放到 该Reference注册的 ReferenceQueue, 对应于我们这里 ref 会被放到 referenceQueue
然后 我们这里的消费线程, 从队列里面取引用, 拿到数据, 打印日志 "gc will collect ... "
这就是一个相对比较常规的流程
3. Test02WeakReferenceAfterGc$Obj 重写 finalize
增加一个 referenceProcessor.process_discovered_references 里面 process_discovered_reflist(_discoveredFinalRefs 断点
3.1 process_discovered_reflist(_discoveredFinalRefs 处理之前
打印 _discoveredFinalRefs 列表的数据如下
java.lang.ref.Finalizer
{0x00000007426cf9e8} - klass: 'java/lang/ref/Finalizer'- ---- fields (total size 5 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/io/FileInputStream'{0x00000007404dbdb0} (e809b7b6 e84d073a)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x00000007426839d0} (e84d073a 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d6618)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/Finalizer'{0x00000007426b30c0} (e84d6618 e84de472)- private 'next' 'Ljava/lang/ref/Finalizer;' @28 a 'java/lang/ref/Finalizer'{0x00000007426f2390} (e84de472 e84d6618)- private 'prev' 'Ljava/lang/ref/Finalizer;' @32 a 'java/lang/ref/Finalizer'{0x00000007426b30c0} (e84d6618 0)
java.lang.ref.Finalizer
{0x00000007426b30c0} - klass: 'java/lang/ref/Finalizer'- ---- fields (total size 5 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/io/FileInputStream'{0x00000007404e14d8} (e809c29b e84d073a)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x00000007426839d0} (e84d073a 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d2f87)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/Finalizer'{0x0000000742697c38} (e84d2f87 e84d9f3d)- private 'next' 'Ljava/lang/ref/Finalizer;' @28 a 'java/lang/ref/Finalizer'{0x00000007426cf9e8} (e84d9f3d e84d2f87)- private 'prev' 'Ljava/lang/ref/Finalizer;' @32 a 'java/lang/ref/Finalizer'{0x0000000742697c38} (e84d2f87 0)
java.lang.ref.Finalizer
{0x0000000742697c38} - klass: 'java/lang/ref/Finalizer'- ---- fields (total size 5 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'com/hx/test02/Test02WeakReferenceAfterGc$Obj'{0x00000007404e1fa0} (e809c3f4 e84d073a)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x00000007426839d0} (e84d073a 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d2f87)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/Finalizer'{0x0000000742697c38} (e84d2f87 e84d6618)- private 'next' 'Ljava/lang/ref/Finalizer;' @28 a 'java/lang/ref/Finalizer'{0x00000007426b30c0} (e84d6618 0)- private 'prev' 'Ljava/lang/ref/Finalizer;' @32 NULL (0 0)
第三个 FinalReference 为 vm为 我们创建的 Obj 实例 o 创建的 Finalzer
3.2 process_discovered_reflist(_discoveredFinalRefs 处理之后
打印 _discoveredFinalRefs 列表的数据如下
java.lang.ref.Finalizer
{0x00000007426cf9e8} - klass: 'java/lang/ref/Finalizer'- ---- fields (total size 5 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/io/FileInputStream'{0x0000000742770968} (e84ee12d e84d073a)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x00000007426839d0} (e84d073a 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d6618)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/Finalizer'{0x00000007426b30c0} (e84d6618 e84de472)- private 'next' 'Ljava/lang/ref/Finalizer;' @28 a 'java/lang/ref/Finalizer'{0x00000007426f2390} (e84de472 e84d6618)- private 'prev' 'Ljava/lang/ref/Finalizer;' @32 a 'java/lang/ref/Finalizer'{0x00000007426b30c0} (e84d6618 0)
java.lang.ref.Finalizer
{0x00000007426b30c0} - klass: 'java/lang/ref/Finalizer'- ---- fields (total size 5 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/io/FileInputStream'{0x0000000742770988} (e84ee131 e84d073a)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x00000007426839d0} (e84d073a 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d2f87)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/Finalizer'{0x0000000742697c38} (e84d2f87 e84d9f3d)- private 'next' 'Ljava/lang/ref/Finalizer;' @28 a 'java/lang/ref/Finalizer'{0x00000007426cf9e8} (e84d9f3d e84d2f87)- private 'prev' 'Ljava/lang/ref/Finalizer;' @32 a 'java/lang/ref/Finalizer'{0x0000000742697c38} (e84d2f87 0)
java.lang.ref.Finalizer
{0x0000000742697c38} - klass: 'java/lang/ref/Finalizer'- ---- fields (total size 5 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'com/hx/test02/Test02WeakReferenceAfterGc$Obj'{0x00000007427709a8} (e84ee135 e84d073a)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x00000007426839d0} (e84d073a 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d2f87)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/Finalizer'{0x0000000742697c38} (e84d2f87 e84d6618)- private 'next' 'Ljava/lang/ref/Finalizer;' @28 a 'java/lang/ref/Finalizer'{0x00000007426b30c0} (e84d6618 0)- private 'prev' 'Ljava/lang/ref/Finalizer;' @32 NULL (0 0)
可以看到 这个 我们创建的 Obj 实例 o 对应的 FinalReference 依然存在于 discoverList, 这就意味着之后 这个 FinalReference 之后会被添加到 它对应的 ReferenceQueue, 然后 FinalizerThread 线程 进行 finalize 的相关业务处理
注意, 这个 处理的过程的 process_phase3 这里传递的 clear_referent 为 false, 表示 需要将 Obj 实例 o, 复制到 存活区, FinalReference 依赖这个对象
3.3 process_discovered_reflist(_discoveredPhantomRefs 处理之前
打印 _discoveredPhantomRefs 列表的数据如下
## 省略掉部分无关的 CleanerImpl$PhantomCleanableRef, Cleaner
java.lang.ref.PhantomReference
{0x0000000742683bb8} - klass: 'java/lang/ref/PhantomReference'- ---- fields (total size 4 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'com/hx/test02/Test02WeakReferenceAfterGc$Obj'{0x00000007404e1fa0} (e809c3f4 e84d0773)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742683b98} (e84d0773 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e84d0777)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/PhantomReference'{0x0000000742683bb8} (e84d0777 0)
这里的 PhantomReference 为 我们为 我们创建的 Obj 实例 o 创建的 PhantomReference
3.4 process_discovered_reflist(_discoveredPhantomRefs 处理之后
打印 _discoveredPhantomRefs 列表的数据如下
## 省略掉部分无关的 CleanerImpl$PhantomCleanableRef, Cleaner
# 找不到 0x0000000742683bb8 对应的 PhantomReference 了
这里我们发现 Obj 的实例 o 对应的 PhantomReference ref 被从 discoverList 里面移除了
这个是因为 上面处理 o 对应的 FinalReference 的时候, 将 o 复制到了 存活区, 因此 这里在 o 对应的 PhantomReference 处理 process_phase2 的时候, 因为 PhantomReference 还存活, 所以将 PhantomReference ref 移出了 discoverList
所以 在 第一个 System.gc 的时候 Obj 的实例 o 对应的 FinalReference 进入了 Finalizer.queue
但是 Obj 的实例 o 对应的 PhantomReference ref 没有进入其对应的 referenceQueue
3.5 第二次 System.gc process_discovered_reflist(_discoveredFinalRefs 处理之前
打印 _discoveredFinalRefs 列表的数据如下
java.lang.ref.Finalizer
{0x00000007422741d8} - klass: 'java/lang/ref/Finalizer'- ---- fields (total size 5 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/ClassLoader$NativeLibrary'{0x00000007426d3dd8} (e84da7bb e84487a3)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742243d18} (e84487a3 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e844b086)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/Finalizer'{0x0000000742258430} (e844b086 e84521bd)- private 'next' 'Ljava/lang/ref/Finalizer;' @28 a 'java/lang/ref/Finalizer'{0x0000000742290de8} (e84521bd e844b086)- private 'prev' 'Ljava/lang/ref/Finalizer;' @32 a 'java/lang/ref/Finalizer'{0x0000000742258430} (e844b086 0)
java.lang.ref.Finalizer
{0x0000000742258430} - klass: 'java/lang/ref/Finalizer'- ---- fields (total size 5 words):- private strict 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/ClassLoader$NativeLibrary'{0x00000007426d3e00} (e84da7c0 e84487a3)- volatile strict 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x0000000742243d18} (e84487a3 0)- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0 e844b086)- private transient strict 'discovered' 'Ljava/lang/ref/Reference;' @24 a 'java/lang/ref/Finalizer'{0x0000000742258430} (e844b086 e844e83b)- private 'next' 'Ljava/lang/ref/Finalizer;' @28 a 'java/lang/ref/Finalizer'{0x00000007422741d8} (e844e83b 0)- private 'prev' 'Ljava/lang/ref/Finalizer;' @32 NULL (0 0)
没有了 Obj 实例对应的 o 的 FinalReference, 没有 强引用引用关联 该 FinalReference 了, 复制算法 Discover 不到该 FinalReference
3.6 第二次 System.gc process_discovered_reflist(_discoveredPhantomRefs 处理之前
打印 _discoveredPhantomRefs 列表的数据如下
## 省略掉部分无关的 CleanerImpl$PhantomCleanableRef, Cleaner
# 找不到 0x0000000742683bb8 对应的 PhantomReference 了
没有了 Obj 实例对应的 o 的 PhantomReference, 没有 强引用引用关联 该 PhantomReference了, 复制算法 Discover 不到该 PhantomReference
所以 第二次 gc 的时候, Obj 的实例 o 对应的 PhantomReference ref 没有进入其对应的 referenceQueue
经过这一次 gc, 一般情况下 Obj 实例 o, 对应的 FinalReference 已经处理了 finalize 的相关业务[sleep 3s], 并且 FinalizerThread 处理了该 FinalReference的后续流程, Obj 的实例 o, o 对应的 FinalReference, o 对应的 PhantomReference 都会被处理掉
4. 如何确保 o 对应的 PhantomReference 入队
相信看完了 上面的这一系列, 你应该有办法了吧
参考
https://hllvm-group.iteye.com/group/topic/34934
https://blog.csdn.net/KevinMite/article/details/83745080
01 PhantomReference没有进入ReferenceQueue相关推荐
- 如何成为一个区块链开发人员_成为开发人员是社会工作
如何成为一个区块链开发人员 Times have changed since the old days when an IT professional was this typical shy per ...
- weakreference_Java中WeakReference,SoftReference,PhantomReference和Strong Reference之间的区别...
weakreference 很长一段时间以来,WeakReference和SoftReference都已添加到Java API中,但是并不是每个Java程序员都熟悉它. 这意味着在Java中使用Wea ...
- Java中WeakReference,SoftReference,PhantomReference和Strong Reference之间的区别
很长一段时间以来,WeakReference和SoftReference都已添加到Java API中,但是并不是每个Java程序员都熟悉它. 这意味着在Java中使用WeakReference和Sof ...
- Java源码:Reference与ReferenceQueue
一:Reference与ReferenceQueue Reference的四种状态: Active:活跃,内存一开始分配的常有状态,垃圾收集器进行对该引用可达性分析后会进入Pending或Inacti ...
- 详细分析Android中的引用机制Reference(WeakReference、SoftReference、PhantomReference)
目录 1.前言 2.四种引用 3.java.lang.ref 4.Reference 5.ReferenceQueue.enqueue(Reference) 6.ReferenceQueue.isEn ...
- Reference定义(PhantomReference,Cleaner)
Java NIO ByteBuffer详解:[url]http://donald-draper.iteye.com/blog/2357084[/url] MappedByteBuffer定义:[url ...
- java 源码系列 - 带你读懂 Reference 和 ReferenceQueue
java 源码系列 - 带你读懂 Reference 和 ReferenceQueue https://blog.csdn.net/gdutxiaoxu/article/details/8073858 ...
- 深入理解StrongReference,SoftReference, WeakReference和PhantomReference
Java 中一共有 4 种类型的引用 : StrongReference. SoftReference. WeakReference 以及 PhantomReference (传说中的幽灵引用 呵呵) ...
- Java ~ Reference ~ PhantomReference【源码】
前言 文章 相关系列:<Java ~ Reference[目录]>(持续更新) 相关系列:<Java ~ Reference ~ PhantomReference[源码]>(学 ...
最新文章
- 硬刚一周,3W字总结,一年的经验告诉你如何准备校招!
- Scala集合体系:可变集合和不可变集合
- Apache状态监测集重启
- hutool 读取扩展名文件_用卓语言实现中文编程显示隐藏文件扩展名
- 【ARM】Tiny4412裸板编程之MMU(段 16M)
- 【Linux】一步一步学Linux——iptables命令(186)
- MySQL高级之查询优化(索引失效)
- SAP Spartacus 服务器端渲染的三种可能情形
- 计算机一级上机考试试题题库,2016年计算机一级上机考试题库
- 什么是静态,静态有什么作用呢?
- 量子计算机 长生不老,这种准粒子“长生不老”,有望提升量子计算机性能
- redmine 自己定义字段mysql表结构
- eclipse经常出现弹窗Refreshing workspace
- numpy库的安装方法
- 以锅炉安全为例,台账管理在安全建设中的作用
- 寻找春天nbsp;九宫格日记-2014.04.26
- Interlocked.Increment 方法 和Interlocked.Decrement 方法作用
- [PPPOE]PPPD源码分析
- 个人自建数据库和云数据库有什么区别?
- 安卓证书免费在线制作工具