JNI - question about jmethodid values.

coleen.phillimore at oracle.com coleen.phillimore at oracle.com
Tue Nov 27 23:52:12 UTC 2018

Hi I have a couple of comments.

On 11/26/18 2:33 PM, Thomas Stüfe wrote:
> Hey JC,
> On Mon, Nov 26, 2018 at 8:15 PM JC Beyler <jcbeyler at google.com> wrote:
>> Hi all,
>> Just added my two cents on one comment:
>> On Mon, Nov 26, 2018 at 5:00 AM Thomas Stüfe <thomas.stuefe at gmail.com> wrote:
>>> Hi Peter,
>>> On Mon, Nov 26, 2018 at 1:02 PM Peter Hull <peterhull90 at gmail.com> wrote:
>>>> Hi Thomas,
>>>> Thank you very much for the detailed explanation. For your
>>>> information, the relevant NetBeans bug is
>>>> https://issues.apache.org/jira/browse/NETBEANS-1428
>>>> On Sat, Nov 24, 2018 at 3:41 PM Thomas Stüfe <thomas.stuefe at gmail.com> wrote:
>>>>> A jmethodid is a pointer to malloc'ed memory.
>>>> OK. Just in case I haven't understood it - does this mean a jmethodid,
>>>> once 'created', won't change (after garbage collection or whatever)?
>>> yes. It lives on, unchanged, forever. Even if the associated class is
>>> unloaded. That must be since outside JNI/JVMTI code may call in with
>>> outdated jmethodids which we must be able to handle gracefully.
>> This is the current design and most likely will remain for quite a bit but it is not defined by the SPEC to be like this so, in essence, it is an implementation detail that could be not true in future releases ;-)
> I politely disagree :)
> JNI spec says that you have a function like this:
> jmethodID GetMethodID(..)
> returning a jmethodid which you can then use in subsequent JNI
> functions. These functions are required to behave in a predictable way
> if the jmethodid has gotten invalid. The spec has no way to inform the
> caller if a jmethodid has gotten invalid by class unloading. Since the
> jmethodid is handed up to the caller and stored by him, there is no
> way to change its value on the fly either.
> So even though the spec does not specifically say that jmethodid lives
> forever, it is laid out in a way that prevents jmethodids from ever
> becoming invalid, and from changing their numerical value. This can of
> course change, but not without changing the JNI spec.
> I think my point is that Peter can rely on this behavior without fear
> that it will change in the future without him noticing. Before this
> behavior changes, the JNI spec would have to change.
> Cheers, Thomas

If the class is unloaded, the jmethodID is cleared.  Native code should 
first test whether it's NULL.  I think that is the predictable behavior 
that the spec requires.

Also, the jmethodIDs were never in the PermGen but in CHeap allocated 
memory blocks.  The Method* that was in the jmethodID was in the 
permgen.  I don't think there was any guarantee of contiguity (is that a 
word) but they are allocated together in a block.  After permgen was 
removed, the blocks were sorted by class loader, so that the class 
loader data could point to them for clearing.


>> Thanks,
>> Jc
>>>>> But it is not guaranteed to work. I would probably rather use a
>>>>> hashmap or similar.
>>>> I need to look at the implications on more detail but think it would
>>>> make sense to use long/jlong instead of int/jint on all platforms; the
>>>> extra memory use shouldn't be a problem. I think the IDs are just
>>>> stored on the Java side and used to get the method name and signature
>>>> later. That should be a loss-free cast, shouldn't it?
>>> Sure.
>>>>> If this is
>>>>> true, this 4x30bit assumption may actually have worked before jdk8,
>>>>> since the java heap is allocated as one continuous space, with the
>>>>> PermGen clustered in one part of it.
>>>> Indeed we did only start to get crashes on JDK9 and later (only
>>>> observed on Windows, macOS seems OK and other platforms have not been
>>>> tested)
>>>> Yours sincerely,
>>>> Peter
>>> Cheers, Thomas
>> --
>> Thanks,
>> Jc

More information about the discuss mailing list