RFR: 8365192: post_meth_exit should be in vm state when calling get_jvmti_thread_state [v4]
Serguei Spitsyn
sspitsyn at openjdk.org
Thu Aug 14 15:01:11 UTC 2025
On Thu, 14 Aug 2025 09:15:03 GMT, Serguei Spitsyn <sspitsyn at openjdk.org> wrote:
>> src/hotspot/share/prims/jvmtiExport.cpp line 1838:
>>
>>> 1836: {
>>> 1837: ThreadInVMfromJava tiv(thread);
>>> 1838: state = get_jvmti_thread_state(thread);
>>
>> The issue I see is that `get_jvmti_thread_state()` can safepoint for virtual threads (and now also for platform threads because of `~ThreadInVMfromJava`), which brings us back to the bug 8255452 was trying to fix: if there is a return oop at the top of the stack, it could become invalid if a GC occurs. I think we will have to unconditionally save the return value in case it's an oop, before doing anything else.
>
> Thank you, Patricio! Good catch and suggestion.
This can be kind of intrusive, something like below (without changes from Leonid):
@@ -1830,6 +1830,16 @@ void JvmtiExport::post_method_entry(JavaThread *thread, Method* method, frame cu
void JvmtiExport::post_method_exit(JavaThread* thread, Method* method, frame current_frame) {
HandleMark hm(thread);
methodHandle mh(thread, method);
+ Handle result;
+ jvalue value;
+ oop oop_result;
+ BasicType type = current_frame.interpreter_frame_result(&oop_result, &value);
+
+ value.j = 0L;
+ if (is_reference_type(type)) {
+ result = Handle(thread, oop_result);
+ value.l = JNIHandles::make_local(thread, result());
+ }
JvmtiThreadState *state = get_jvmti_thread_state(thread);
@@ -1841,21 +1851,15 @@ void JvmtiExport::post_method_exit(JavaThread* thread, Method* method, frame cur
// return a flag when a method terminates by throwing an exception
// i.e. if an exception is thrown and it's not caught by the current method
bool exception_exit = state->is_exception_detected() && !state->is_exception_caught();
- Handle result;
- jvalue value;
- value.j = 0L;
if (state->is_enabled(JVMTI_EVENT_METHOD_EXIT)) {
// if the method hasn't been popped because of an exception then we populate
// the return_value parameter for the callback. At this point we only have
// the address of a "raw result" and we just call into the interpreter to
// convert this into a jvalue.
- if (!exception_exit) {
- oop oop_result;
- BasicType type = current_frame.interpreter_frame_result(&oop_result, &value);
+ if (exception_exit) {
if (is_reference_type(type)) {
- result = Handle(thread, oop_result);
- value.l = JNIHandles::make_local(thread, result());
+ value.j = 0L;
}
}
}
Not sure yet how to make it simpler.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/26713#discussion_r2276882958
More information about the serviceability-dev
mailing list