On Mon, 14 Jul 2025 21:42:42 GMT, Serguei Spitsyn <sspit...@openjdk.org> wrote:
>> src/hotspot/share/prims/jvmti.xml line 5904: >> >>> 5902: <error id="JVMTI_ERROR_OPAQUE_FRAME"> >>> 5903: The implementation is unable to get the frame locals >>> 5904: (e.g. the frame at <code>depth</code> is executing a native >>> method). >> >> Is this true, especially the native method handling? I'm looking at changes >> needed on the JDWP and JDI side, and currently they don't even handle >> OPAQUE_FRAME. I get the feeling native methods produce >> JVMTI_ERROR_INVALID_SLOT . >> >> For JDWP and JDI things are similar for GetLocalXXX() with the exception >> that they expect OPAQUE_FRAME when not dealing with a mounted virtual thread >> suspended at a breakpoint. So basically that means OPAQUE_FRAME handling did >> not exist before virtual threads. > > Thank you for the concern. But I'm kind of puzzled with your observation. > The JVMTI implementation should return `JVMTI_ERROR_OPAQUE_FRAME` for > platform threads. > Though I wonder if it also was the case before virtual thread support was > added. > > The `VM_BaseGetOrSetLocal::doit()` have the following checks in place: > > > void VM_BaseGetOrSetLocal::doit() { > . . . > frame fr = _jvf->fr(); > if (_set && _depth != 0 && > Continuation::is_frame_in_continuation(_jvf->thread(), fr)) { > _result = JVMTI_ERROR_OPAQUE_FRAME; // deferred locals are not fully > supported in continuations > return; > } > Method* method = _jvf->method(); > if (getting_receiver()) { > if (method->is_static()) { > _result = JVMTI_ERROR_INVALID_SLOT; ### This check is for > GetLocalInstance > return; > } > } else { > if (method->is_native()) { > _result = JVMTI_ERROR_OPAQUE_FRAME; ### This check is before calls to > ### check_slot_type_no_lvt() and > check_slot_type_lvt() > return; > } > if (!check_slot_type_no_lvt(_jvf)) { ### This has checks for > JVMTI_ERROR_INVALID_SLOT > return; > } > if (method->has_localvariable_table() && > !check_slot_type_lvt(_jvf)) { ### This has checks for > JVMTI_ERROR_INVALID_SLOT > return; > } > } > . . . My concern was that Set/GetLocal could produce JVMTI_ERROR_OPAQUE_FRAME for a native frame, and JDI was not handling this, but is appears that JDI is prevening Set/GetLocal on a native frame. Read on for more details. It looks like historically Set/GetLocal has returned JVMTI_ERROR_OPAQUE_FRAME for native methods. However, JDI does not check for this, so I had some concern about that because JVMTI_ERROR_OPAQUE_FRAME would result in a JDIInternalError. However, I think now that JDI would never result in a JVMTI Set/GetLocal call when the frame is native because of checks JDI does ahead of time. The JDI Set/GetValue APIs take a LocalVariable, the source of which would preclude ever getting one for a frame that is for a native method. I think what is most common is to call StackFrame.visibleVariables() to get all the LocalVariables, and if this is done on a native method, you simply get no LocalVariables, thus you have nothing to pass to Set/GetLocal. So I think the only time JDI will see JVMTI_ERROR_OPAQUE_FRAME is for the virtual thread case, which for SetLocal requires that the frame be the topmost frame and the virtual thread be mounted. The JDI spec is already covering this, so probably no changes are needed. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/26111#discussion_r2205981269