Skip to content

Instantly share code, notes, and snippets.

@rednaxelafx
Created January 31, 2012 10:02
Show Gist options
  • Save rednaxelafx/1709717 to your computer and use it in GitHub Desktop.
Save rednaxelafx/1709717 to your computer and use it in GitHub Desktop.
follow up (3): Example of NIO direct memory OOME on JDK7b147 https://gist.github.com/1704102
$ java -XX:+PrintReferenceGC -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:MaxDirectMemorySize=10m -XX:+UseSerialGC -XX:+TraceReferenceGC -Xbootclasspath/p:altclasses -XX:InitialHeapSize=16777216 -XX:MaxHeapSize=268435456 NativeMemoryGC | more
[GC VM option '+PrintReferenceGC'
VM option '+DisableExplicitGC'
VM option '+PrintGCDetails'
VM option 'MaxDirectMemorySize=10m'
VM option '+UseSerialGC'
VM option '+TraceReferenceGC'
VM option 'InitialHeapSize=16777216'
VM option 'MaxHeapSize=268435456'
[DefNewsun.misc.Cleaner @ 0x00000000eb2d0630 being discovered
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0xbbbb50] print_stack_trace_on(outputStream*)+0x20
V [libjvm.so+0xbbe6d1] ReferenceProcessor::discover_reference(oopDesc*, ReferenceType)+0x291
V [libjvm.so+0x7c9b5c] instanceRefKlass::oop_oop_iterate_nv(oopDesc*, FastScanClosure*)+0x6bc
V [libjvm.so+0xc2bbc5] ContiguousSpace::oop_since_save_marks_iterate_nv(FastScanClosure*)+0xb5
V [libjvm.so+0x648d4d] DefNewGeneration::oop_since_save_marks_iterate_nv(FastScanClosure*)+0x4d
V [libjvm.so+0x730dde] GenCollectedHeap::oop_since_save_marks_iterate(int, FastScanClosure*, FastScanClosure*)+0x2e
V [libjvm.so+0x6467f4] DefNewGeneration::FastEvacuateFollowersClosure::do_void()+0x24
V [libjvm.so+0x6493cb] DefNewGeneration::collect(bool, bool, unsigned long, bool)+0x25b
V [libjvm.so+0x73002c] GenCollectedHeap::do_collection(bool, bool, unsigned long, bool, int)+0x88c
V [libjvm.so+0x57e567] GenCollectorPolicy::satisfy_failed_allocation(unsigned long, bool)+0x2e7
V [libjvm.so+0xd3d9e4] VM_GenCollectForAllocation::doit()+0x94
V [libjvm.so+0xd5a5f1] VM_Operation::evaluate()+0x91
V [libjvm.so+0xd57a62] VMThread::evaluate_operation(VM_Operation*)+0xc2
V [libjvm.so+0xd59169] VMThread::loop()+0x459
V [libjvm.so+0xd593b5] VMThread::run()+0xb5
V [libjvm.so+0xb0de64] java_start(Thread*)+0xf4
Thread 0 gets list 0x0000000012cb1af0
Enqueued reference (0x00000000eb2d0630: sun.misc.Cleaner)
Thread 0 gets list 0x0000000012cb1ad8
Enqueued reference (0x00000000eb2d4ab0: java.lang.ref.Finalizer)
sun.misc.Cleaner @ 0x00000000eb2d57c0 being discovered
Thread 0 gets list 0x0000000012cb1af0
Enqueued reference (0x00000000eb2d57c0: sun.misc.Cleaner)
Thread 0 gets list 0x0000000012cb1ad8
Enqueued reference (0x00000000eb2da568: java.lang.ref.Finalizer)
sun.misc.Cleaner @ 0x00000000eb2dd448 being discovered
Thread 0 gets list 0x0000000012cb1af0

In DefNewGeneration::collect(),

  FastEvacuateFollowersClosure evacuate_followers(gch, _level, this,
                                                  &fsc_with_no_gc_barrier,
                                                  &fsc_with_gc_barrier);

  assert(gch->no_allocs_since_save_marks(0),
         "save marks have not been newly set.");

  gch->gen_process_strong_roots(_level,
                                true,  // Process younger gens, if any,
                                       // as strong roots.
                                true,  // activate StrongRootsScope
                                false, // not collecting perm generation.
                                SharedHeap::SO_AllClasses,
                                &fsc_with_no_gc_barrier,
                                true,   // walk *all* scavengable nmethods
                                &fsc_with_gc_barrier);

  // "evacuate followers".
  evacuate_followers.do_void();

  FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
  ReferenceProcessor* rp = ref_processor();
  rp->setup_policy(clear_all_soft_refs);
  rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
                                    NULL);

The stack trace we got from this example is in a "evacuate followers" phase, with evacuate_followers.do_void()

void DefNewGeneration::FastEvacuateFollowersClosure::do_void() {
  do {
    _gch->oop_since_save_marks_iterate(_level, _scan_cur_or_nonheap,
                                       _scan_older);
  } while (!_gch->no_allocs_since_save_marks(_level));
  guarantee(_gen->promo_failure_scan_is_complete(), "Failed to finish scan");
}
  // Apply "blk->do_oop" to the addresses of all reference fields in objects
  // starting with the _saved_mark_word, which was noted during a generation's
  // save_marks and is required to denote the head of an object.
  // Fields in objects allocated by applications of the closure
  // *are* included in the iteration.
  // Updates _saved_mark_word to point to just after the last object
  // iterated over.
#define ContigSpace_OOP_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix)  \
  void oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk);

  ALL_SINCE_SAVE_MARKS_CLOSURES(ContigSpace_OOP_SINCE_SAVE_MARKS_DECL)
#undef ContigSpace_OOP_SINCE_SAVE_MARKS_DECL
#define ContigSpace_OOP_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix)  \
                                                                          \
void ContiguousSpace::                                                    \
oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) {            \
  HeapWord* t;                                                            \
  HeapWord* p = saved_mark_word();                                        \
  assert(p != NULL, "expected saved mark");                               \
                                                                          \
  const intx interval = PrefetchScanIntervalInBytes;                      \
  do {                                                                    \
    t = top();                                                            \
    while (p < t) {                                                       \
      Prefetch::write(p, interval);                                       \
      debug_only(HeapWord* prev = p);                                     \
      oop m = oop(p);                                                     \
      p += m->oop_iterate(blk);                                           \
    }                                                                     \
  } while (t < top());                                                    \
                                                                          \
  set_saved_mark_word(p);                                                 \
}

ALL_SINCE_SAVE_MARKS_CLOSURES(ContigSpace_OOP_SINCE_SAVE_MARKS_DEFN)

#undef ContigSpace_OOP_SINCE_SAVE_MARKS_DEFN

and coming down to the following code when scanning through a weakref instance

#define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains)        \
  if (closure->apply_to_weak_ref_discovered_field()) {                          \
    T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);           \
    closure->do_oop##nv_suffix(disc_addr);                                      \
  }                                                                             \
                                                                                \
  T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);           \
  T heap_oop = oopDesc::load_heap_oop(referent_addr);                           \
  if (!oopDesc::is_null(heap_oop) && contains(referent_addr)) {                 \
    ReferenceProcessor* rp = closure->_ref_processor;                           \
    oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);                 \
    if (!referent->is_gc_marked() && (rp != NULL) &&                            \
        rp->discover_reference(obj, reference_type())) {                        \
      return size;                                                              \
    } else {                                                                    \
      /* treat referent as normal oop */                                        \
      SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
      closure->do_oop##nv_suffix(referent_addr);                                \
    }                                                                           \
  }                                                                             \
  /* treat next as normal oop */                                                \
  T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);                   \
  if (contains(next_addr)) {                                                    \
    SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \
    closure->do_oop##nv_suffix(next_addr);                                      \
  }                                                                             \
  return size;                                                                  \

Promoted sun.misc.Cleaners are recorded in the card table during reference processing.

template <class T>
inline void DefNewGeneration::KeepAliveClosure::do_oop_work(T* p) {
#ifdef ASSERT
  {
    // We never expect to see a null reference being processed
    // as a weak reference.
    assert (!oopDesc::is_null(*p), "expected non-null ref");
    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
    assert (obj->is_oop(), "expected an oop while scanning weak refs");
  }
#endif // ASSERT

  _cl->do_oop_nv(p);

  // Card marking is trickier for weak refs.
  // This oop is a 'next' field which was filled in while we
  // were discovering weak references. While we might not need
  // to take a special action to keep this reference alive, we
  // will need to dirty a card as the field was modified.
  //
  // Alternatively, we could create a method which iterates through
  // each generation, allowing them in turn to examine the modified
  // field.
  //
  // We could check that p is also in an older generation, but
  // dirty cards in the youngest gen are never scanned, so the
  // extra check probably isn't worthwhile.
  if (Universe::heap()->is_in_reserved(p)) {
    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
    _rs->inline_write_ref_field_gc(p, obj);
  }
}

template <class T>
inline void DefNewGeneration::FastKeepAliveClosure::do_oop_work(T* p) {
#ifdef ASSERT
  {
    // We never expect to see a null reference being processed
    // as a weak reference.
    assert (!oopDesc::is_null(*p), "expected non-null ref");
    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
    assert (obj->is_oop(), "expected an oop while scanning weak refs");
  }
#endif // ASSERT

  _cl->do_oop_nv(p);

  // Optimized for Defnew generation if it's the youngest generation:
  // we set a younger_gen card if we have an older->youngest
  // generation pointer.
  oop obj = oopDesc::load_decode_heap_oop_not_null(p);
  if (((HeapWord*)obj < _boundary) && Universe::heap()->is_in_reserved(p)) {
    _rs->inline_write_ref_field_gc(p, obj);
  }
}

So in the second young GC in this example, the sun.misc.Cleaners in the old generation are scanned, but not processed, as shown in the following log:

sun.misc.Cleaner @ 0x00000000f0589fd8 being discovered
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xbbbb50]  print_stack_trace_on(outputStream*)+0x20
V  [libjvm.so+0xbbe6bb]  ReferenceProcessor::discover_reference(oopDesc*, ReferenceType)+0x27b
V  [libjvm.so+0x7bec94]  instanceRefKlass::oop_oop_iterate_nv(oopDesc*, FilteringClosure*)+0x1e4
V  [libjvm.so+0xc2f0fe]  ContiguousSpaceDCTOC::walk_mem_region_with_cl(MemRegion, HeapWord*, HeapWord*, FilteringClosure*)+0x16e
V  [libjvm.so+0xc29359]  Filtering_DCTOC::walk_mem_region(MemRegion, HeapWord*, HeapWord*)+0x89
V  [libjvm.so+0xc2a7b8]  DirtyCardToOopClosure::do_MemRegion(MemRegion)+0x1a8
V  [libjvm.so+0x4c2dc8]  ClearNoncleanCardWrapper::do_MemRegion(MemRegion)+0x2d8
V  [libjvm.so+0x4bf694]  CardTableModRefBS::non_clean_card_iterate_work(MemRegion, MemRegionClosure*, bool)+0x3f4
V  [libjvm.so+0x4bf7e2]  CardTableModRefBS::non_clean_card_iterate(Space*, MemRegion, DirtyCardToOopClosure*, MemRegionClosure*, bool)+0x72
V  [libjvm.so+0x4c11af]  CardTableRS::younger_refs_in_space_iterate(Space*, OopsInGenClosure*)+0x8f
V  [libjvm.so+0x741e70]  OneContigSpaceCardGeneration::younger_refs_iterate(OopsInGenClosure*)+0x40
V  [libjvm.so+0x72f326]  GenCollectedHeap::gen_process_strong_roots(int, bool, bool, bool, SharedHeap::ScanningOption, OopsInGenClosure*, bool, OopsInGenClosure*)+0xc6
V  [libjvm.so+0x6493c3]  DefNewGeneration::collect(bool, bool, unsigned long, bool)+0x253
V  [libjvm.so+0x73002c]  GenCollectedHeap::do_collection(bool, bool, unsigned long, bool, int)+0x88c
V  [libjvm.so+0x57e567]  GenCollectorPolicy::satisfy_failed_allocation(unsigned long, bool)+0x2e7
V  [libjvm.so+0xd3d9d4]  VM_GenCollectForAllocation::doit()+0x94
V  [libjvm.so+0xd5a5e1]  VM_Operation::evaluate()+0x91
V  [libjvm.so+0xd57a52]  VMThread::evaluate_operation(VM_Operation*)+0xc2
V  [libjvm.so+0xd59159]  VMThread::loop()+0x459
V  [libjvm.so+0xd593a5]  VMThread::run()+0xb5
V  [libjvm.so+0xb0de64]  java_start(Thread*)+0xf4

  this reference is not in the originating generation

And for the "reference not active" case:

sun.misc.Cleaner @ 0x00000000f06b2b98 being discovered
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xbbbb50]  print_stack_trace_on(outputStream*)+0x20
V  [libjvm.so+0xbbe6bb]  ReferenceProcessor::discover_reference(oopDesc*, ReferenceType)+0x27b
V  [libjvm.so+0x7c9b5c]  instanceRefKlass::oop_oop_iterate_nv(oopDesc*, FastScanClosure*)+0x6bc
V  [libjvm.so+0xc2bbb5]  ContiguousSpace::oop_since_save_marks_iterate_nv(FastScanClosure*)+0xb5
V  [libjvm.so+0x7438ad]  OneContigSpaceCardGeneration::oop_since_save_marks_iterate_nv(FastScanClosure*)+0x3d
V  [libjvm.so+0x730dfb]  GenCollectedHeap::oop_since_save_marks_iterate(int, FastScanClosure*, FastScanClosure*)+0x4b
V  [libjvm.so+0x6467f4]  DefNewGeneration::FastEvacuateFollowersClosure::do_void()+0x24
V  [libjvm.so+0x6493cb]  DefNewGeneration::collect(bool, bool, unsigned long, bool)+0x25b
V  [libjvm.so+0x73002c]  GenCollectedHeap::do_collection(bool, bool, unsigned long, bool, int)+0x88c
V  [libjvm.so+0x57e567]  GenCollectorPolicy::satisfy_failed_allocation(unsigned long, bool)+0x2e7
V  [libjvm.so+0xd3d9d4]  VM_GenCollectForAllocation::doit()+0x94
V  [libjvm.so+0xd5a5e1]  VM_Operation::evaluate()+0x91
V  [libjvm.so+0xd57a52]  VMThread::evaluate_operation(VM_Operation*)+0xc2
V  [libjvm.so+0xd59159]  VMThread::loop()+0x459
V  [libjvm.so+0xd593a5]  VMThread::run()+0xb5
V  [libjvm.so+0xb0de64]  java_start(Thread*)+0xf4

  this reference is not active
sun.misc.Cleaner @ 0x00000000f06ceb18 being discovered
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xbbbb50]  print_stack_trace_on(outputStream*)+0x20
V  [libjvm.so+0xbbe6bb]  ReferenceProcessor::discover_reference(oopDesc*, ReferenceType)+0x27b
V  [libjvm.so+0x7c9b5c]  instanceRefKlass::oop_oop_iterate_nv(oopDesc*, FastScanClosure*)+0x6bc
V  [libjvm.so+0xc2bbb5]  ContiguousSpace::oop_since_save_marks_iterate_nv(FastScanClosure*)+0xb5
V  [libjvm.so+0x7438ad]  OneContigSpaceCardGeneration::oop_since_save_marks_iterate_nv(FastScanClosure*)+0x3d
V  [libjvm.so+0x730dfb]  GenCollectedHeap::oop_since_save_marks_iterate(int, FastScanClosure*, FastScanClosure*)+0x4b
V  [libjvm.so+0x6467f4]  DefNewGeneration::FastEvacuateFollowersClosure::do_void()+0x24
V  [libjvm.so+0x6493cb]  DefNewGeneration::collect(bool, bool, unsigned long, bool)+0x25b
V  [libjvm.so+0x73002c]  GenCollectedHeap::do_collection(bool, bool, unsigned long, bool, int)+0x88c
V  [libjvm.so+0x57e567]  GenCollectorPolicy::satisfy_failed_allocation(unsigned long, bool)+0x2e7
V  [libjvm.so+0xd3d9d4]  VM_GenCollectForAllocation::doit()+0x94
V  [libjvm.so+0xd5a5e1]  VM_Operation::evaluate()+0x91
V  [libjvm.so+0xd57a52]  VMThread::evaluate_operation(VM_Operation*)+0xc2
V  [libjvm.so+0xd59159]  VMThread::loop()+0x459
V  [libjvm.so+0xd593a5]  VMThread::run()+0xb5
V  [libjvm.so+0xb0de64]  java_start(Thread*)+0xf4

  this reference is not active
sun.misc.Cleaner @ 0x00000000f06ceb60 being discovered
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xbbbb50]  print_stack_trace_on(outputStream*)+0x20
V  [libjvm.so+0xbbe6bb]  ReferenceProcessor::discover_reference(oopDesc*, ReferenceType)+0x27b
V  [libjvm.so+0x7c9b5c]  instanceRefKlass::oop_oop_iterate_nv(oopDesc*, FastScanClosure*)+0x6bc
V  [libjvm.so+0xc2bbb5]  ContiguousSpace::oop_since_save_marks_iterate_nv(FastScanClosure*)+0xb5
V  [libjvm.so+0x7438ad]  OneContigSpaceCardGeneration::oop_since_save_marks_iterate_nv(FastScanClosure*)+0x3d
V  [libjvm.so+0x730dfb]  GenCollectedHeap::oop_since_save_marks_iterate(int, FastScanClosure*, FastScanClosure*)+0x4b
V  [libjvm.so+0x6467f4]  DefNewGeneration::FastEvacuateFollowersClosure::do_void()+0x24
V  [libjvm.so+0x6493cb]  DefNewGeneration::collect(bool, bool, unsigned long, bool)+0x25b
V  [libjvm.so+0x73002c]  GenCollectedHeap::do_collection(bool, bool, unsigned long, bool, int)+0x88c
V  [libjvm.so+0x57e567]  GenCollectorPolicy::satisfy_failed_allocation(unsigned long, bool)+0x2e7
V  [libjvm.so+0xd3d9d4]  VM_GenCollectForAllocation::doit()+0x94
V  [libjvm.so+0xd5a5e1]  VM_Operation::evaluate()+0x91
V  [libjvm.so+0xd57a52]  VMThread::evaluate_operation(VM_Operation*)+0xc2
V  [libjvm.so+0xd59159]  VMThread::loop()+0x459
V  [libjvm.so+0xd593a5]  VMThread::run()+0xb5
V  [libjvm.so+0xb0de64]  java_start(Thread*)+0xf4

  this reference is not in the originating generation

...

Heap
 def new generation   total 4928K, used 4927K [0x00000000eae00000, 0x00000000eb350000, 0x00000000f0350000)
  eden space 4416K, 100% used [0x00000000eae00000, 0x00000000eb250000, 0x00000000eb250000)
  from space 512K,  99% used [0x00000000eb250000, 0x00000000eb2cfff8, 0x00000000eb2d0000)
  to   space 512K,   0% used [0x00000000eb2d0000, 0x00000000eb2d0000, 0x00000000eb350000)
 tenured generation   total 10944K, used 7772K [0x00000000f0350000, 0x00000000f0e00000, 0x00000000fae00000)
   the space 10944K,  71% used [0x00000000f0350000, 0x00000000f0ae7258, 0x00000000f0ae7400, 0x00000000f0e00000)
 compacting perm gen  total 21248K, used 4842K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
   the space 21248K,  22% used [0x00000000fae00000, 0x00000000fb2ba958, 0x00000000fb2baa00, 0x00000000fc2c0000)
No shared spaces configured.
diff -r 8389681cd7b1 src/share/vm/memory/referenceProcessor.cpp
--- a/src/share/vm/memory/referenceProcessor.cpp Tue Nov 15 16:44:09 2011 -0800
+++ b/src/share/vm/memory/referenceProcessor.cpp Tue Jan 31 18:00:48 2012 +0800
@@ -33,6 +33,41 @@
#include "runtime/java.hpp"
#include "runtime/jniHandles.hpp"
+#include "runtime/frame.inline.hpp"
+#include "runtime/os.hpp"
+#include "utilities/decoder.hpp"
+
+void print_stack_trace_on(outputStream* st) {
+ // don't allocate large buffer on stack
+ static char buf[O_BUFLEN];
+
+ frame fr = os::current_frame();
+
+ // see if it's a valid frame
+ if (fr.pc()) {
+ st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
+
+ // initialize decoder to decode C frames
+ Decoder decoder;
+
+ int count = 0;
+ while (count++ < StackPrintLimit) {
+ fr.print_on_error(st, buf, sizeof(buf));
+ st->cr();
+ if (os::is_first_C_frame(&fr)) break;
+ fr = os::get_sender_for_C_frame(&fr);
+ }
+
+ if (count > StackPrintLimit) {
+ st->print_cr("...<more frames>...");
+ }
+ }
+ if (Thread::current()->is_Java_thread()) {
+ ((JavaThread*) Thread::current())->print_stack_on(st);
+ }
+ st->cr();
+}
+
ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL;
ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL;
oop ReferenceProcessor::_sentinelRef = NULL;
@@ -1187,14 +1222,36 @@
// and complexity in processing these references.
// We call this choice the "RefeferentBasedDiscovery" policy.
bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) {
+ static bool printed_stack_trace = false;
+ bool is_cleaner = false;
+ {
+ ResourceMark rm;
+ char* klass_name = obj->blueprint()->name()->as_C_string();
+ if (strcmp("sun/misc/Cleaner", klass_name) == 0 && PrintGCDetails && TraceReferenceGC) {
+ is_cleaner = true;
+ gclog_or_tty->print_cr("sun.misc.Cleaner @ " INTPTR_FORMAT " being discovered",
+ obj);
+ if (!printed_stack_trace) {
+ printed_stack_trace = true;
+ print_stack_trace_on(gclog_or_tty);
+ }
+ }
+ }
+
// We enqueue references only if we are discovering refs
// (rather than processing discovered refs).
if (!_discovering_refs || !RegisterReferences) {
+ if (is_cleaner && TraceReferenceGC && PrintGCDetails) {
+ gclog_or_tty->print_cr(" not discovering refs");
+ }
return false;
}
// We only enqueue active references.
oop next = java_lang_ref_Reference::next(obj);
if (next != NULL) {
+ if (is_cleaner && TraceReferenceGC && PrintGCDetails) {
+ gclog_or_tty->print_cr(" this reference is not active");
+ }
return false;
}
@@ -1204,6 +1261,9 @@
// Reference is not in the originating generation;
// don't treat it specially (i.e. we want to scan it as a normal
// object with strong references).
+ if (is_cleaner && TraceReferenceGC && PrintGCDetails) {
+ gclog_or_tty->print_cr(" this reference is not in the originating generation");
+ }
return false;
}
@@ -1212,6 +1272,9 @@
if (is_alive_non_header() != NULL) {
verify_referent(obj);
if (is_alive_non_header()->do_object_b(java_lang_ref_Reference::referent(obj))) {
+ if (is_cleaner && TraceReferenceGC && PrintGCDetails) {
+ gclog_or_tty->print_cr(" the referent is reachable");
+ }
return false; // referent is reachable
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment