RFR: 8309399: JVMTI spec needs to clarify when OPAQUE_FRAME is thrown for reasons other than a native method [v7]
Serguei Spitsyn
sspitsyn at openjdk.org
Tue Jul 15 03:02:38 UTC 2025
On Mon, 14 Jul 2025 23:23:21 GMT, Chris Plummer <cjplummer at openjdk.org> wrote:
>> 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.
Okay, thanks. This sounds right. 👍
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/26111#discussion_r2206180435
More information about the hotspot-dev
mailing list