When allocating a new oop we allocate memory for an oopDesc, fill in certain parts of that memory, and cast the memory to an oop.
This means we never call an oopDesc constructor. That approach to "constructing" an oopDesc is only valid if its default constructor is trivial. And it can only be trivial if all it's members have trivial default constructors.
C++14 3.8 Object lifetime, paragraph 1, says
The lifetime of an object of type T begins when:
— storage with the proper alignment and size for type T is obtained, and
— if the object has non-trivial initialization, its initialization is complete.
But oopDesc has a markWord member, and markWord's default constructor is not trivial:
markWord() { /* uninitialized */ }
As a result, the lifetime of the oopDesc object never begins, and accesses via ordinary oopDesc member functions are invalid. We may not have been running afoul of this because we've been building with -fno-lifetime-dse since JDK-8151841.
The intent of the existing constructor is to be "trivial", but this definition preceeds the availability of C++11/14 default definitions in HotSpot. The default markWord constructor should be changed to be trivial.