mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8310829: guarantee(!HAS_PENDING_EXCEPTION) failed in ExceptionTranslation::doit
Reviewed-by: never, kvn
This commit is contained in:
parent
456bf115aa
commit
f6bdccb45c
6 changed files with 155 additions and 53 deletions
|
@ -374,6 +374,15 @@ bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char**
|
|||
// Shared code for translating an exception from HotSpot to libjvmci or vice versa.
|
||||
class ExceptionTranslation: public StackObj {
|
||||
protected:
|
||||
enum DecodeFormat {
|
||||
_encoded_ok = 0, // exception was successfully encoded into buffer
|
||||
_buffer_alloc_fail = 1, // native memory for buffer could not be allocated
|
||||
_encode_oome_fail = 2, // OutOfMemoryError thrown during encoding
|
||||
_encode_fail = 3 // some other problem occured during encoding. If buffer != 0,
|
||||
// buffer contains a `struct { u4 len; char[len] desc}`
|
||||
// describing the problem
|
||||
};
|
||||
|
||||
JVMCIEnv* _from_env; // Source of translation. Can be null.
|
||||
JVMCIEnv* _to_env; // Destination of translation. Never null.
|
||||
|
||||
|
@ -382,49 +391,34 @@ class ExceptionTranslation: public StackObj {
|
|||
// Encodes the exception in `_from_env` into `buffer`.
|
||||
// Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size`
|
||||
// and the encoding was written to `buffer` otherwise returns -N.
|
||||
virtual int encode(JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) = 0;
|
||||
virtual int encode(JavaThread* THREAD, jlong buffer, int buffer_size) = 0;
|
||||
|
||||
// Decodes the exception in `buffer` in `_to_env` and throws it.
|
||||
virtual void decode(JavaThread* THREAD, Klass* vmSupport, jlong buffer) = 0;
|
||||
virtual void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) = 0;
|
||||
|
||||
public:
|
||||
void doit(JavaThread* THREAD) {
|
||||
// Resolve VMSupport class explicitly as HotSpotJVMCI::compute_offsets
|
||||
// may not have been called.
|
||||
Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, THREAD);
|
||||
guarantee(!HAS_PENDING_EXCEPTION, "");
|
||||
|
||||
int buffer_size = 2048;
|
||||
while (true) {
|
||||
ResourceMark rm;
|
||||
jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, jbyte, buffer_size);
|
||||
if (buffer == 0L) {
|
||||
decode(THREAD, vmSupport, 0L);
|
||||
JVMCI_event_1("error translating exception: translation buffer allocation failed");
|
||||
decode(THREAD, _buffer_alloc_fail, 0L);
|
||||
return;
|
||||
}
|
||||
int res = encode(THREAD, vmSupport, buffer, buffer_size);
|
||||
if (_from_env != nullptr && !_from_env->is_hotspot() && _from_env->has_pending_exception()) {
|
||||
// Cannot get name of exception thrown by `encode` as that involves
|
||||
// calling into libjvmci which in turn can raise another exception.
|
||||
_from_env->clear_pending_exception();
|
||||
decode(THREAD, vmSupport, -2L);
|
||||
int res = encode(THREAD, buffer, buffer_size);
|
||||
if (_to_env->has_pending_exception()) {
|
||||
// Propagate pending exception
|
||||
return;
|
||||
} else if (HAS_PENDING_EXCEPTION) {
|
||||
Symbol *ex_name = PENDING_EXCEPTION->klass()->name();
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) {
|
||||
decode(THREAD, vmSupport, -1L);
|
||||
} else {
|
||||
decode(THREAD, vmSupport, -2L);
|
||||
}
|
||||
return;
|
||||
} else if (res < 0) {
|
||||
}
|
||||
if (res < 0) {
|
||||
int required_buffer_size = -res;
|
||||
if (required_buffer_size > buffer_size) {
|
||||
buffer_size = required_buffer_size;
|
||||
}
|
||||
} else {
|
||||
decode(THREAD, vmSupport, buffer);
|
||||
decode(THREAD, _encoded_ok, buffer);
|
||||
if (!_to_env->has_pending_exception()) {
|
||||
_to_env->throw_InternalError("decodeAndThrowThrowable should have thrown an exception");
|
||||
}
|
||||
|
@ -439,7 +433,26 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
|
|||
private:
|
||||
const Handle& _throwable;
|
||||
|
||||
int encode(JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) {
|
||||
int encode(JavaThread* THREAD, jlong buffer, int buffer_size) {
|
||||
Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
|
||||
Symbol *ex_name = throwable->klass()->name();
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) {
|
||||
JVMCI_event_1("error translating exception: OutOfMemoryError");
|
||||
decode(THREAD, _encode_oome_fail, 0L);
|
||||
} else {
|
||||
char* char_buffer = (char*) buffer + 4;
|
||||
stringStream st(char_buffer, (size_t) buffer_size - 4);
|
||||
java_lang_Throwable::print_stack_trace(throwable, &st);
|
||||
u4 len = (u4) st.size();
|
||||
*((u4*) buffer) = len;
|
||||
JVMCI_event_1("error translating exception: %s", char_buffer);
|
||||
decode(THREAD, _encode_fail, buffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
JavaCallArguments jargs;
|
||||
jargs.push_oop(_throwable);
|
||||
jargs.push_long(buffer);
|
||||
|
@ -452,11 +465,11 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
|
|||
return result.get_jint();
|
||||
}
|
||||
|
||||
void decode(JavaThread* THREAD, Klass* vmSupport, jlong buffer) {
|
||||
void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) {
|
||||
JNIAccessMark jni(_to_env, THREAD);
|
||||
jni()->CallStaticVoidMethod(JNIJVMCI::VMSupport::clazz(),
|
||||
JNIJVMCI::VMSupport::decodeAndThrowThrowable_method(),
|
||||
buffer, false);
|
||||
format, buffer, false);
|
||||
}
|
||||
public:
|
||||
HotSpotToSharedLibraryExceptionTranslation(JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle& throwable) :
|
||||
|
@ -468,15 +481,25 @@ class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation {
|
|||
private:
|
||||
jthrowable _throwable;
|
||||
|
||||
int encode(JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) {
|
||||
int encode(JavaThread* THREAD, jlong buffer, int buffer_size) {
|
||||
JNIAccessMark jni(_from_env, THREAD);
|
||||
return jni()->CallStaticIntMethod(JNIJVMCI::VMSupport::clazz(),
|
||||
int res = jni()->CallStaticIntMethod(JNIJVMCI::VMSupport::clazz(),
|
||||
JNIJVMCI::VMSupport::encodeThrowable_method(),
|
||||
_throwable, buffer, buffer_size);
|
||||
if (jni()->ExceptionCheck()) {
|
||||
// Cannot get name of exception thrown as that can raise another exception.
|
||||
jni()->ExceptionClear();
|
||||
JVMCI_event_1("error translating exception: unknown error");
|
||||
decode(THREAD, _encode_fail, 0L);
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void decode(JavaThread* THREAD, Klass* vmSupport, jlong buffer) {
|
||||
void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) {
|
||||
Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, CHECK);
|
||||
JavaCallArguments jargs;
|
||||
jargs.push_int(format);
|
||||
jargs.push_long(buffer);
|
||||
jargs.push_int(true);
|
||||
JavaValue result(T_VOID);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue