Question about jmethodId and class unloading

Thomas Stüfe thomas.stuefe at gmail.com
Fri Apr 15 10:21:19 UTC 2022


Thanks Andrei.

I idly wonder then whether it would be worth coming up with some different
mechanism, especially in the context of a possible re-examination of AGCT.
Maybe jmethodID is not the right vehicle then.

Just spitballing: if at the end of the day all async-profiler needs to mark
a frame is file+line (is it?), we could hand back strings instead (maybe
internally cached in a hash map), or some sort of opaque string handles, or
some sort of pseudo PC with a safe resolution mechanism behind it that
gracefully handles class unloading.

Cheers, Thomas


On Fri, Apr 15, 2022 at 11:41 AM Andrei Pangin <andrei.pangin at gmail.com>
wrote:

> Hi,
> AFAIK, there is no [legal] way to resolve jmethodID at the time of calling
> AsyncGetCallTrace, since this usually happens in a signal handler, and no
> JNI / JVM TI Method function is async signal safe. Furthermore, they expect
> a thread to be in _thread_in_native state, while an asynchronous signal may
> come at any thread state.
>
> Andrei
>
> пт, 15 апр. 2022 г. в 11:44, Thomas Stüfe <thomas.stuefe at gmail.com>:
>
>> Thank you David, that makes sense.
>>
>> From the answers I take that my technical assumption is correct: there is
>> no graceful way to prevent crashes or ending up with the wrong Method* if
>> you misuse jmethodid. And that its the responsibility of the JNI
>> programmer
>> to make sure the jmethodid is valid. So he has to know about class
>> unloading and, wrt AGCT, make sure you don't use the method ids beyond the
>> frame that called AGCT. async-profiler in particular should resolve the
>> method id right away in their SIGPROF handler (I suppose they do; Idk. I
>> have not looked at the sources yet).
>>
>> Cheers, Thomas
>>
>> On Thu, Apr 14, 2022 at 9:55 AM David Holmes <david.holmes at oracle.com>
>> wrote:
>>
>> > On 14/04/2022 12:25 am, Thomas Stüfe wrote:
>> > > Thank you, Volker.
>> > >
>> > > I was actually concerned about AsyncGetCallTrace, which seems to
>> return
>> > > just an array of jmethodIds as stack. These could become invalid the
>> > moment
>> > > they are handed out.
>> >
>> > They would still be valid when the call to AGCT returns as the methods
>> > are still on the stack. Now if the caller of AGCT simply stashes away
>> > those jmethodIds for later use by some other piece of code, then yes
>> > that is a problem. But that is the problem of the user of AGCT not AGCT
>> > itself - no?
>> >
>> > Cheers,
>> > David
>> >
>> > > Cheers, Thomas
>> > >
>> > > On Wed, Apr 13, 2022 at 2:51 PM Volker Simonis <
>> volker.simonis at gmail.com
>> > >
>> > > wrote:
>> > >
>> > >> For an instance method you need an instance of that class anyway if
>> you
>> > >> want to call the method, so the class can't be unloaded.
>> > >>
>> > >> But in general you're right, JNI gives you no guarantees at all. It
>> even
>> > >> explicitly warns about this situation. See:
>> > >>
>> >
>> https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#accessing_fields_and_methods
>> > >>
>> > >> Thomas Stüfe <thomas.stuefe at gmail.com> schrieb am Mi., 13. Apr.
>> 2022,
>> > >> 12:22:
>> > >>
>> > >>> Hi,
>> > >>>
>> > >>> In hotspot, jmethodId is an address to a slot in a table-like
>> > structure of
>> > >>> Method*. We ensure that the slot never goes away, so the slot
>> address
>> > is
>> > >>> always valid. But we reuse the slot - if a class is unloaded, its
>> > method
>> > >>> ids are released by marking their slot with a canary. Later it could
>> > get
>> > >>> reused for a different Method*.
>> > >>>
>> > >>> I must miss something really obvious, but what prevents an outside
>> > caller
>> > >>> from using an invalid or outdated method id via JNI?
>> > >>>
>> > >>> If the method id got released, on CallXXXMethod, we stop the VM
>> with a
>> > >>> fatal JNI error (if CheckJNICalls=1). But there is no way to
>> gracefully
>> > >>> continue, right?
>> > >>>
>> > >>> And what happens if the slot got reused by the VM, so it now
>> contains a
>> > >>> different Method* ? There is no way catch that, right?
>> > >>>
>> > >>> Do both cases just boil down to "the JNI programmer should know when
>> > class
>> > >>> unloading did happen, and should not use the jmethodid beyond that
>> > point"?
>> > >>>
>> > >>> Thanks a lot,
>> > >>>
>> > >>> Thomas
>> > >>>
>> > >>
>> >
>>
>


More information about the hotspot-runtime-dev mailing list