C1 code installation and JNIHandle::deleted_handle() oop

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Tue Nov 14 16:23:07 UTC 2017


>> Looking at the crash log, the problematic code is under assert:
>>
>> void ConstantOopWriteValue::write_on(DebugInfoWriteStream* stream) {
>>    assert(JNIHandles::resolve(value()) == NULL ||
>>           Universe::heap()->is_in_reserved(JNIHandles::resolve(value())),
>>           "Should be in heap");
>>    stream->write_int(CONSTANT_OOP_CODE);
>>    stream->write_handle(value());
>> }
>>
>> So, the proper fix would be to make the verification code more robust.
> 
> Actually, in Shenandoah case, the failure is here (it is obscured by inlining, but visible in
> slowdebug):
>    http://hg.openjdk.java.net/jdk/hs/file/5caa1d5f74c1/src/hotspot/share/runtime/jniHandles.hpp#l220
> 
> ... "== deleted_handle()" or "!= deleted_handle()". So fortifying assert code does not help, the bug
> is touching the oop in improper thread state. Nightmarish scenario would be to fail "!="/"==" check
> because the deleted_handle oop had been already updated, but the actual handle value did not.

> The similar thing happens after we write the oop into the debug stream: it is not handelize-d
> anymore, and so opaque for GC, and thus has all the chance to be garbled by the time GC finishes.

I don't follow you. Can you point to the code you are talking about?

ConstantOopWriteValue::write_on() writes the _handle_ and not the naked 
oop [1].

I still believe the assert is the only problem here. If it's valuable to 
keep it, then it should perform all necessary precautions itself before 
accessing the oop.

The assert is a relatively recent addition. It was added as part of 
PermGen removal and most likely the fact it isn't executed in VM was 
overlooked.

Best regards,
Vladimir Ivanov

[1]

void ConstantOopWriteValue::write_on(DebugInfoWriteStream* stream) {
...
stream->write_handle(value());

...

class ConstantOopWriteValue: public ScopeValue {
  private:
   jobject _value;
  public:
   jobject value() const                { return _value;  }
...

void DebugInfoWriteStream::write_handle(jobject h) {
   write_int(recorder()->oop_recorder()->find_index(h));
}


Best regards,
Vladimir Ivanov

> Having these two thoughts in mind, I think we have to consider _thread_in_vm on that C1 path. But
> where exactly?
> 
> Thanks,
> -Aleksey
> 


More information about the hotspot-compiler-dev mailing list