JDK-8160399 : is_oop_or_null involves undefined behavior
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2016-06-27
  • Updated: 2020-05-06
  • Resolved: 2017-08-24
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.
JDK 10
10 b22Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
oopDesc::is_oop_or_null is an ordinary member function, whose definition includes a test using the expression "this == NULL".  However, this can be assumed to never be NULL, as that would require undefined behavior. So the compiler is free to optimize away that test, eliminating the "_or_null" part of the function's intended semantics.  Recent versions of gcc (like gcc 6) seem to be more aggressive about optimizations around that sort of thing, leading to crashes.

Comments
For it to fail one has to take a non-oop, make it appear to be an oop, and call an oop member function on that not really an oop. That sounds like UB to me.
16-08-2017

The is_oop() function checks out the value of the "this" pointer - is that also undefined behavior? // used only for asserts bool oopDesc::is_oop(bool ignore_mark_word) const { oop obj = (oop) this; if (!check_obj_alignment(obj)) return false; if (!Universe::heap()->is_in_reserved(obj)) return false; // obj is aligned and accessible in heap if (Universe::heap()->is_in_reserved(obj->klass_or_null())) return false; // Header verification: the mark is typically non-NULL. If we're // at a safepoint, it must not be null. // Outside of a safepoint, the header could be changing (for example, // another thread could be inflating a lock on this object). if (ignore_mark_word) { return true; } if (mark() != NULL) { return true; } return !SafepointSynchronize::is_at_safepoint(); }
16-08-2017

When I've queried such code in the past I was told it was okay because the compiler implemented member function calls like: a->foo(args); as foo(a, args) where the first parameter is passed as "this" and hence a check for "this == NULL" was valid. Of course that was then ...
28-06-2016