JDK-8043538 : assert(o->is_oop_or_null()) failed: should always be an oop, at heapDumper.cpp:724
  • Type: Bug
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: 8,9
  • Priority: P5
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2014-05-20
  • Updated: 2019-02-11
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Related Reports
Relates :  
When doing a heap dump with jmap or jcmd an assert can fail in jdk8 and 9.
The assert fails because the heap dumper is trying to inspect an object that is dead.

Unexpected Error
Internal Error at heapDumper.cpp:724, pid=27154, tid=139872669280000
assert(o->is_oop_or_null()) failed: should always be an oop

Analysis from Mikael Gerdin:
Object o1 in region r1 points to humongous object o2 in r2.
o1 and o2 are not reachable.
r2 is freed and later re-used for some other purpose.
(since o2 is not evacuated the reference from o1 is not updated)
r1 is considered expensive to evacuate and is kept around.

A heap dump is requested, which performs object_iterate on all in-use regions.
object_iterate provides a callback to the HeapDumper for each object, dead or 

The HeapDumper iterates over all the fields of the object and at this point 
o1's reference field which used to point to o2 can now point to arbitrary heap 

Loading and decoding the oop is fine, but the assert will fail.
In product builds nothing bad will happen, except that the hprof file will have a strange pointer in it.
Defering this to tbd_major since it is not a problem in production.

We should probably just remove the if (ClassUnloadingWithConcurrentMark) check around is_obj_dead in HeapRegion::block_is_obj. It seems weird that G1 should allow code iterate over dead objects even though the Klass* is safe to read.