<div dir="ltr"><div dir="ltr">On Sun, Jun 8, 2025 at 8:19 PM David Holmes <<a href="mailto:david.holmes@oracle.com">david.holmes@oracle.com</a>> wrote:</div><div class="gmail_quote gmail_quote_container"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 6/06/2025 1:23 am, Jiangli Zhou wrote:<br>
> On Thu, Jun 5, 2025 at 1:33 AM David Holmes <<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a> <br>
> <mailto:<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a>>> wrote:<br>
>  ><br>
>  > On 5/06/2025 1:33 am, Jiangli Zhou wrote:<br>
>  > > Ok, still thanks for the thoughts, David.<br>
>  > ><br>
>  > > To summarize, here is what we can do for the current step:<br>
>  > ><br>
>  > > - Allow JNI_OnLoad_L and etc for JDK internal native libraries with<br>
>  > > the dynamic linking case.<br>
>  > > - JNI spec already allows JNI_OnLoad_L and etc for dynamically linked<br>
>  > > native libraries. No spec change is required to the above.<br>
>  ><br>
>  > Sorry but where does the spec allow this? I thought we had agreed that<br>
>  > this was a limitation of the implementation in regard to detecting<br>
>  > whether a library is loaded dynamically or statically, and that we<br>
>  > needed to document this case in the spec. ??<br>
> <br>
> It's based on the following (referenced in <a href="https://mail.openjdk.org/" rel="noreferrer" target="_blank">https://mail.openjdk.org/</a> <br>
> pipermail/leyden-dev/2025-May/002144.html <<a href="https://mail.openjdk.org/" rel="noreferrer" target="_blank">https://mail.openjdk.org/</a> <br>
> pipermail/leyden-dev/2025-May/002144.html> message) specified in <br>
> <a href="https://docs.oracle.com/en/java/javase/21/docs/specs/jni/" rel="noreferrer" target="_blank">https://docs.oracle.com/en/java/javase/21/docs/specs/jni/</a> <br>
> invocation.html#support-for-statically-linked-libraries <https:// <br>
> <a href="http://docs.oracle.com/en/java/javase/21/docs/specs/jni/" rel="noreferrer" target="_blank">docs.oracle.com/en/java/javase/21/docs/specs/jni/</a> <br>
> invocation.html#support-for-statically-linked-libraries>:<br>
> <br>
>     Support for Statically Linked Libraries<br>
> <br>
> <br>
>     "If dynamically linked library defines JNI_OnLoad_L and/or<br>
>     JNI_OnUnload_L functions, these functions will be ignored."<br>
> <br>
> There are two parts to the above. The first part indicates that the spec <br>
> allows JNI_OnLoad_L and/or JNI_OnUnload_L being defined in a dynamically <br>
> linked library.<br>
<br>
I don't agree that you can split that one sentence into two parts to <br>
allow the first section to be a justification of allowing JNI_OnLoad_L <br>
in a dynamically linked library. The intent of this part of to say these <br>
functions should not exist but if they do we will ignore them.<br>
<br>
We have a situation where the spec is clear in intent, but the <br>
implementation doesn't have enough information to accurately implement <br>
what the spec states.<br>
<br>
So the intent here is to document this gap between the spec and <br>
implementation by adding a note to the spec.<br></blockquote><div><br></div><div>Thanks, David. Your interpretation and reasoning sounds ok to me. More importantly, we have consensus on documenting the case with implicitly loaded dynamically linked native libraries. I'll file a bug.</div><div><br></div><div>Best</div><div>Jiangli</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
David<br>
-----<br>
<br>
> The second part stating "these functions will be ignored" however does <br>
> not reflect the limitation of the implementation when handling <br>
> implicitly loaded native libraries. That part needs to be documented.<br>
> <br>
> Please let me know if that's more clear.<br>
> <br>
> Best,<br>
> <br>
> Jiangli<br>
> <br>
>  ><br>
>  > David<br>
>  > -----<br>
>  ><br>
>  > > - JNI_OnLoad_L and etc should not be called for dynamically linked<br>
>  > > native libraries when the library is loaded due to loadLibrary() by<br>
>  > > default. If a dynamic library is already loaded as a dependency of<br>
>  > > other native libraries, when loadLibrary() is called for the library,<br>
>  > > JNI_OnLoad_L can be called. That is an existing behavior since JDK 8.<br>
>  > > Need to document (in spec or release notes?).<br>
>  > ><br>
>  > > Best,<br>
>  > > Jiangli<br>
>  > ><br>
>  > > On Tue, Jun 3, 2025 at 9:31 PM David Holmes <br>
> <<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a> <mailto:<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a>>> wrote:<br>
>  > >><br>
>  > >> On 4/06/2025 5:00 am, Jiangli Zhou wrote:<br>
>  > >>> On Mon, Jun 2, 2025 at 6:22 PM David Holmes <br>
> <<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a> <mailto:<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a>>> wrote:<br>
>  > >>>><br>
>  > >>>> On 3/06/2025 9:29 am, Jiangli Zhou wrote:<br>
>  > >>>>> On Sun, Jun 1, 2025 at 7:55 PM David Holmes <br>
> <<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a> <mailto:<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a>>> wrote:<br>
>  > >>>>>><br>
>  > >>>>>> On 31/05/2025 7:20 am, Jiangli Zhou wrote:<br>
>  > >>>>>>> On Thu, May 29, 2025 at 11:54 PM David Holmes <br>
> <<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a> <mailto:<a href="mailto:david.holmes@oracle.com" target="_blank">david.holmes@oracle.com</a>>> wrote:<br>
>  > >>>>>>>><br>
>  > >>>>>>>> On 30/05/2025 9:26 am, Jiangli Zhou wrote:<br>
>  > >>>>>>>>><br>
>  > >>>>>>>>> I just thought of one more thing related to the discussion <br>
> now. Any<br>
>  > >>>>>>>>> concern if the implementation does not ignore JNI_OnLoad_L <br>
> and etc if<br>
>  > >>>>>>>>> they are defined application's dynamically linked native <br>
> libraries? Or<br>
>  > >>>>>>>>> that's unspecified behavior and it's up to the implement to <br>
> decide?<br>
>  > >>>>>>>><br>
>  > >>>>>>>> For Internal libraries or external? For external you have to <br>
> follow the<br>
>  > >>>>>>>> spec - if both methods exist you only want to execute one of <br>
> them.<br>
>  > >>>>>>><br>
>  > >>>>>>> It's for the external (non-JDK) library that I'm a bit more <br>
> cautious.<br>
>  > >>>>>>><br>
>  > >>>>>>> In the existing code in JDK mainline,<br>
>  > >>>>>>> <a href="https://github.com/openjdk/jdk/" rel="noreferrer" target="_blank">https://github.com/openjdk/jdk/</a> <br>
> blob/3cc630985d47be6ba4cf991698e999f17dbde203/src/java.base/share/ <br>
> classes/jdk/internal/loader/NativeLibraries.java#L117 <https:// <br>
> <a href="http://github.com/openjdk/jdk/blob/3cc630985d47be6ba4cf991698e999f17dbde203/" rel="noreferrer" target="_blank">github.com/openjdk/jdk/blob/3cc630985d47be6ba4cf991698e999f17dbde203/</a> <br>
> src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java#L117>,<br>
>  > >>>>>>> loadLibrary() first tries to find the built-in library using<br>
>  > >>>>>>> JNI_OnLoad_L symbol (L is the library name). When dlsym is <br>
> called to<br>
>  > >>>>>>> find the symbol from the main process, any of the already loaded<br>
>  > >>>>>>> shared libraries are also searched, as described by the dlsym <br>
> man page<br>
>  > >>>>>>> (included related part below).<br>
>  > >>>>>>><br>
>  > >>>>>>> <a href="https://man7.org/linux/man-pages/man3/dlsym.3.html" rel="noreferrer" target="_blank">https://man7.org/linux/man-pages/man3/dlsym.3.html</a> <https:// <br>
> <a href="http://man7.org/linux/man-pages/man3/dlsym.3.html" rel="noreferrer" target="_blank">man7.org/linux/man-pages/man3/dlsym.3.html</a>>:<br>
>  > >>>>>>>            RTLD_DEFAULT<br>
>  > >>>>>>>                   Find the first occurrence of the desired <br>
> symbol using the<br>
>  > >>>>>>>                   default shared object search order.  The <br>
> search will<br>
>  > >>>>>>>                   include global symbols in the executable <br>
> and its<br>
>  > >>>>>>>                   dependencies, as well as symbols in shared <br>
> objects that<br>
>  > >>>>>>>                   were dynamically loaded with the <br>
> RTLD_GLOBAL flag.<br>
>  > >>>>>>><br>
>  > >>>>>>> I think it would be rare, it is possible to construct such case:<br>
>  > >>>>>>><br>
>  > >>>>>>> There are user JNI libraries A and B, with B is built as a <br>
> dependency<br>
>  > >>>>>>> of A. A defines JNI_OnLoad_A and JNI_OnLoad. B defines <br>
> JNI_OnLoad_B<br>
>  > >>>>>>> and JNI_OnLoad. When A is being loaded using loadLibrary(),<br>
>  > >>>>>>> loadLibrary() tries first to lookup JNI_OnLoad_A, which is <br>
> not found.<br>
>  > >>>>>>> A is then loaded dynamically, which causes B being loaded <br>
> implicitly<br>
>  > >>>>>>> as a dependency of A. Later when loadLibrary() is called for B,<br>
>  > >>>>>>> JNI_OnLoad_B would be found and then called. This is an existing<br>
>  > >>>>>>> behavior. I think it's an unspecified behavior and we don't <br>
> need to<br>
>  > >>>>>>> add any additional checks to prevent JNI_OnLoad_B from being <br>
> called.<br>
>  > >>>>>><br>
>  > >>>>>> That sounds like a significant design flaw to me. You can't <br>
> specify that<br>
>  > >>>>>> JNI_OnLoad_L will only be called if L is statically linked, if the<br>
>  > >>>>>> existence of JNI_OnLoad_L is used to infer that L is <br>
> statically linked!<br>
>  > >>>>>> I would expect libraries to have both versions of the OnLoad <br>
> functions<br>
>  > >>>>>> to allow for them being statically or dynamically linked - <br>
> which the<br>
>  > >>>>>> spec allows for by saying the alternate variant is ignored. <br>
> But then the<br>
>  > >>>>>> JDK will execute the wrong method if it finds JNI_OnLoad_L in a<br>
>  > >>>>>> dynamically linked library.<br>
>  > >>>>><br>
>  > >>>>> JNI_OnLoad_L is used to determine if a requested JNI native <br>
> library is<br>
>  > >>>>> a built-in (statically linked) library. Thus, it can avoid the<br>
>  > >>>>> operation of explicit loading for the shared library, e.g. with <br>
> dlopen<br>
>  > >>>>> on Linux. JNI_OnLoad_L is expected to provide the same <br>
> implementation<br>
>  > >>>>> as JNI_OnLoad besides being used as an identifier of a built-in<br>
>  > >>>>> library, IIUC.<br>
>  > >>>>><br>
>  > >>>>> In the scenario that I described in the previous message, when <br>
> a JNI<br>
>  > >>>>> shared library is already implicitly loaded as a dependency of <br>
> another<br>
>  > >>>>> native library, dlopen for explicitly loading the shared library is<br>
>  > >>>>> not necessary. From the implementation point of view, the code <br>
> seems<br>
>  > >>>>> to have been doing the right thing since JDK 8. I did some <br>
> search and<br>
>  > >>>>> found <a href="https://stackoverflow.com/questions/32302262/does-dlopen-" rel="noreferrer" target="_blank">https://stackoverflow.com/questions/32302262/does-dlopen-</a> <br>
> re-load-already-loaded-dependencies-if-so-what-are-the-implication <br>
> <<a href="https://stackoverflow.com/questions/32302262/does-dlopen-re-load-" rel="noreferrer" target="_blank">https://stackoverflow.com/questions/32302262/does-dlopen-re-load-</a> <br>
> already-loaded-dependencies-if-so-what-are-the-implication>,<br>
>  > >>>>> which point out to the following in POSIX spec (latest<br>
>  > >>>>> <a href="https://pubs.opengroup.org/onlinepubs/9799919799/" rel="noreferrer" target="_blank">https://pubs.opengroup.org/onlinepubs/9799919799/</a> <https:// <br>
> <a href="http://pubs.opengroup.org/onlinepubs/9799919799/" rel="noreferrer" target="_blank">pubs.opengroup.org/onlinepubs/9799919799/</a>>):<br>
>  > >>>>><br>
>  > >>>>> "Only a single copy of an executable object file shall be <br>
> brought into<br>
>  > >>>>> the address space, even if dlopen() is invoked multiple times in<br>
>  > >>>>> reference to the executable object file, and even if different<br>
>  > >>>>> pathnames are used to reference the executable object file."<br>
>  > >>>>><br>
>  > >>>>> Then avoiding calling dlopen for the already loaded native library<br>
>  > >>>>> doesn't cause any undesired side effects.<br>
>  > >>>>><br>
>  > >>>>> Perhaps we can update the JNI spec to include the "already <br>
> loaded" JNI<br>
>  > >>>>> native libraries case, in addition to the built-in native <br>
> libraries,<br>
>  > >>>>> regarding JNI_OnLoad_L. Also clarify the "these functions will be<br>
>  > >>>>> ignored" part in JNI spec for the dynamically linked libraries.<br>
>  > >>>>><br>
>  > >>>>> "If dynamically linked library defines JNI_OnLoad_L and/or<br>
>  > >>>>> JNI_OnUnload_L functions, these functions will be ignored."<br>
>  > >>>>><br>
>  > >>>>> Thoughts?<br>
>  > >>>><br>
>  > >>>> The problem is, as I see it, that the spec assumes that if it <br>
> finds the<br>
>  > >>>> JNI_OnLoad_L symbol then L must be a statically linked library. <br>
> But that<br>
>  > >>>> ignores the case you highlight where L was implicitly <br>
> dynamically loaded<br>
>  > >>>> as a dependency on another library. Hence the existence test for the<br>
>  > >>>> symbol is not sufficient to determine if L was statically linked.<br>
>  > >>><br>
>  > >>> Right.<br>
>  > >>><br>
>  > >>>><br>
>  > >>>> If JNI_OnLoad_L and JNI_OnLoad were guaranteed to always do <br>
> exactly the<br>
>  > >>>> same thing it would not make any practical difference, but <br>
> surely that<br>
>  > >>>> is not always the case? I can certainly postulate the existence of a<br>
>  > >>>> library that only needs the "on load" hook for the statically linked<br>
>  > >>>> case, in which case invoking it when actually dynamically linked <br>
> would<br>
>  > >>>> be incorrect and potentially harmful.<br>
>  > >>><br>
>  > >>> Hmmm, I haven't thought of such a case. David, could you please <br>
> give a<br>
>  > >>> concrete example for the case?<br>
>  > >><br>
>  > >> I don't have a concrete example, that's why I just said I could<br>
>  > >> "postulate the existence" of such a case. :)<br>
>  > >><br>
>  > >>>><br>
>  > >>>> It seems we lack a way to know if a given library is truly <br>
> statically<br>
>  > >>>> linked, or to be advised when a library is implicitly loaded as a<br>
>  > >>>> dependency. I am no expert on linking but I've been unable to <br>
> locate any<br>
>  > >>>> information on programmatically determining these conditions.<br>
>  > >>><br>
>  > >>> I haven't found anything either.<br>
>  > >>><br>
>  > >>>><br>
>  > >>>> If there is no real solution then documenting the problem may be <br>
> all we<br>
>  > >>>> can do.<br>
>  > >>><br>
>  > >>> That sounds reasonable to me.<br>
>  > >>><br>
>  > >>> I mentioned the new mailing list discussions to Ron, Alan and Magnus<br>
>  > >>> today during the hermetic Java meeting. They may have follow up<br>
>  > >>> thoughts.<br>
>  > >><br>
>  > >> Okay.<br>
>  > >><br>
>  > >> David<br>
>  > >> -----<br>
>  > >><br>
>  > >><br>
>  > >>> Thanks!<br>
>  > >>> Jiangli<br>
>  > >>><br>
>  > >>>><br>
>  > >>>> David<br>
>  > >>>> -----<br>
>  > >>>><br>
>  > >>>>> Thanks!<br>
>  > >>>>> Jiangli<br>
>  > >><br>
>  ><br>
<br>
</blockquote></div></div>