Questions about the trivial downcall
Jorn Vernee
jorn.vernee at oracle.com
Thu Jul 27 14:50:35 UTC 2023
We have a guarantee in UpcallLinker::on_entry to check that we are
coming from the native thread state:
https://github.com/openjdk/jdk/blob/8650026ff16e5c5eff897f9fd39c0c35fd8b7367/src/hotspot/share/prims/upcallLinker.cpp#L78
(I believe we have a test for that as well).
I think for JNI there's just an assert when we call from native code
into the JNI API and transition to the VM thread state from native:
https://github.com/openjdk/jdk/blob/8650026ff16e5c5eff897f9fd39c0c35fd8b7367/src/hotspot/share/runtime/interfaceSupport.inline.hpp#L98
Jorn
On 27/07/2023 15:44, Maurizio Cimadamore wrote:
>
> The behavior is undefined. It might crash, or not.
>
> While the description says that the downcall should not upcall, please
> note that the Javadoc doesn't say anywhere that ill-behaved downcalls
> will produce new errors. Moreover, the javadoc says this:
>
>> Using this linker option when linking non trivial functions is likely
>> to have adverse effects, such as loss of performance, or JVM crashes.
>>
> Basically, you are in undefined behavior territory. It seems to me
> that you are inferring too much from the javadoc.
>
> While I agree it might be desirable to detect this and log some kind
> of error (see email I sent yesterday), I don't think that, as thing
> stands, the javadoc is incorrect, and/or lacking information.
>
> Maurizio
>
>
> On 27/07/2023 14:40, Cheng Jin wrote:
>>
>> But I tried a simple example to indirectly trigger a JNI upcall
>> within a trivial FFM downcall by saving a global JNIEnv within a JNI
>> downcall at first which works good as follows. Does it mean that a
>> FFM trivial downcall literally doesn’t stop a JNI upcall which seems
>> inconsistent with the description of
>> https://download.java.net/java/early_access/jdk21/docs/api/java.base/java/lang/foreign/Linker.Option.html#isTrivial()
>> <https://urldefense.com/v3/__https://download.java.net/java/early_access/jdk21/docs/api/java.base/java/lang/foreign/Linker.Option.html*isTrivial()__;Iw!!ACWV5N9M2RV99hQ!KpMq9yrQInVdYsiAcZWCDTeOZd_GLJwrDN4n06JvbKQ194M_eabqlUaxzgDuSjbnoxQLukS4Uu8wT7q__xolFW5e$>
>>
>> or OpenJDK doesn’t support such behavior mixed with JNI & FFM?
>>
>> *[1] JniTest.java*
>>
>> public class JniTest {
>>
>> private static Linker linker = Linker.nativeLinker();
>>
>> static {
>>
>> System.loadLibrary("jnitest");
>>
>> }
>>
>> private static final SymbolLookup nativeLibLookup =
>> SymbolLookup.loaderLookup();
>>
>> private native int addJNI2Ints(int arg1, int arg2);
>>
>> public int *addJNI2Ints_Upcall*(int arg1, int arg2) {
>>
>> int sum = arg1 + arg2;
>>
>> System.out.println("trivial: addJNI2Ints_Upcall: sum = " + sum);
>>
>> return sum;
>>
>> }
>>
>> public void test_add2Ints() throws Throwable {
>>
>> FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT,
>> JAVA_INT);
>>
>> MemorySegment functionSymbol = nativeLibLookup.find("add2Ints").get();
>>
>> MethodHandle mh = linker.downcallHandle(functionSymbol, fd,
>> *Linker.Option.isTrivial()*);
>>
>> int result = (int)mh.invokeExact(112, 123);
>>
>> System.out.println("test_add2Ints result = " + result);
>>
>> }
>>
>> public static void main(String[] args) throws Throwable {
>>
>> JniTest test = new JniTest();
>>
>> int sum = test.*addJNI2Ints*(112, 123); ß-- call the JNI native
>> at first to save the global JNIEnv & jobject
>>
>> System.out.println("addJNI2Ints sum = " + sum);
>>
>> test.test_*add2Ints*(); ß-- use saved the global JNIEnv & jobject to
>> trigger a JNI upcall in native.
>>
>> }
>>
>> }
>>
>> *[2] JniTest.c*
>>
>> #include <jni.h>
>>
>> #include "JniTest.h"
>>
>> JNIEnv *globalEnv;
>>
>> jobject globalObj;
>>
>> JNIEXPORT int JNICALL Java_JniTest_addJNI2Ints(JNIEnv *env, jobject
>> thisObj, jint arg1, jint arg2) {
>>
>> jint intSum = arg1 + arg2;
>>
>> globalEnv = env;
>>
>> globalObj = thisObj;
>>
>> printf("\nJava_JniTest_addJNI2Ints: env = %p, globalObj = %p\n",
>> globalEnv, globalObj);
>>
>> return intSum;
>>
>> }
>>
>> int
>>
>> add2Ints(int intArg1, int intArg2)
>>
>> {
>>
>> printf("\nadd2Ints: globalEnv = %p, globalObj = %p\n", globalEnv,
>> globalObj);
>>
>> jclass clazz = (*globalEnv)->GetObjectClass(globalEnv, globalObj);
>>
>> jmethodID method = (*globalEnv)->GetMethodID(globalEnv, clazz,
>> "addJNI2Ints_Upcall", "(II)I");
>>
>> return (*globalEnv)->CallIntMethod(globalEnv, globalObj, method,
>> intArg1, intArg2);
>>
>> }
>>
>> [3]Commands:
>>
>> ./jdk21_hotspot_x86_64/bin/javac --enable-preview --source 21 -h .
>> JniTest.java
>>
>> gcc -fPIC -I"./jdk21_hotspot_x86_64/include"
>> -I"./jdk21_hotspot_x86_64/include/linux" -shared -g -o
>> libjnitest.so JniTest.c
>>
>> ./jdk21_hotspot_x86_64/bin/java --enable-preview
>> -Djava.library.path=./jnitests --enable-native-access=ALL-UNNAMED
>> -Dforeign.restricted=permit JniTest
>>
>> [4] Output:
>>
>> Java_JniTest_addJNI2Ints: env = 0x7f81f8028a08, globalObj =
>> 0x7f81ff379998
>>
>> addJNI2Ints sum = 235
>>
>> add2Ints: intSum = 235
>>
>> add2Ints: globalEnv = 0x7f81f8028a08, globalObj = 0x7f81ff379998
>>
>> *trivial: addJNI2Ints_Upcall: sum = 235 **ß***
>>
>> test_add2Ints result = 235
>>
>> Best Regards
>>
>> Cheng Jin
>>
>> *From:*Maurizio Cimadamore <maurizio.cimadamore at oracle.com>
>> *Sent:* Wednesday, July 26, 2023 8:45 PM
>> *To:* Cheng Jin <jincheng at ca.ibm.com>; panama-dev at openjdk.org
>> *Subject:* [EXTERNAL] Re: Questions about the trivial downcall
>>
>> On 27/07/2023 01: 40, Cheng Jin wrote: >> Right, JNI has not much to
>> do with this. There's different ways to upcall back into Java (JNI
>> and FFM upcall stubs). If so, my understanding is that both JNI and
>> FFM upcall should crash the VM
>>
>> ZjQcmQRYFpfptBannerStart
>>
>> *This Message Is From an External Sender *
>>
>> This message came from outside your organization.
>>
>> * Report Suspicious *
>> <https://us-phishalarm-ewt.proofpoint.com/EWT/v1/PjiDSg!2c-hYpT1IJMQ-iYRkuvEjWPesZVtAje5jWUBYoL2pAM1wRGP31iKedgOBvqFHgP6rIVsAh-wdcVItzgnQJ8qkuKPFDFOpo-3zg$>
>>
>>
>> ZjQcmQRYFpfptBannerEnd
>>
>> On 27/07/2023 01:40, Cheng Jin wrote:
>>
>> >> Right, JNI has not much to do with this. There's different
>> ways to upcall back into Java (JNI and FFM upcall stubs).
>>
>> If so, my understanding is that both JNI and FFM upcall should
>> crash the VM in a trivial FFM downcall, correct?
>>
>> I believe so. Jorn will confirm.
>>
>> Maurizio
>>
>> Best Regards
>>
>> Cheng Jin
>>
>> *From:*Maurizio Cimadamore <maurizio.cimadamore at oracle.com>
>> <mailto:maurizio.cimadamore at oracle.com>
>> *Sent:* Wednesday, July 26, 2023 8:29 PM
>> *To:* Cheng Jin <jincheng at ca.ibm.com>
>> <mailto:jincheng at ca.ibm.com>; panama-dev at openjdk.org
>> <mailto:panama-dev at openjdk.org>
>> *Subject:* [EXTERNAL] Re: Questions about the trivial downcall
>>
>> and does not call back into Java (e. g. using an upcall stub).
>> ß------------------------- it occurs to me that any kind of
>> upcall should be disallowed in such case whether it is JNI or
>> FFM, am I correct? Right, JNI has not much to do with this.
>>
>> ZjQcmQRYFpfptBannerStart
>>
>> *This Message Is From an External Sender *
>>
>> This message came from outside your organization.
>>
>> * Report Suspicious *
>> <https://us-phishalarm-ewt.proofpoint.com/EWT/v1/PjiDSg!2c-gyJS_6lP6sKYb2IHEjb2TaeBqM7xJQ9RStijLaImfla_LrFEK8T2PB5_umxDwUuL8X7BGAHosOeXRLCglJfzdYnJaiHF6gQ$>
>>
>>
>> ZjQcmQRYFpfptBannerEnd
>>
>> and does not call back into Java (e.g. using an upcall stub).
>> ß------------------------- it occurs to me that any kind of
>> upcall should be disallowed in such case whether it is JNI or
>> FFM, am I correct?
>>
>> Right, JNI has not much to do with this. There's different ways
>> to upcall back into Java (JNI and FFM upcall stubs).
>>
>> Your question is: what happens if we do call back when we are in
>> trivial mode.
>>
>> I believe the answer is "we crash" (but not in a "nice way"), and
>> I'm not too sure we can do much to prevent that. I believe Jorn
>> knows more on that topic.
>>
>> Maurizio
>>
>> Best Regards
>>
>> Cheng Jin
>>
>> *From:*Maurizio Cimadamore <maurizio.cimadamore at oracle.com>
>> <mailto:maurizio.cimadamore at oracle.com>
>> *Sent:* Wednesday, July 26, 2023 7:44 PM
>> *To:* Cheng Jin <jincheng at ca.ibm.com>
>> <mailto:jincheng at ca.ibm.com>; panama-dev at openjdk.org
>> <mailto:panama-dev at openjdk.org>
>> *Subject:* [EXTERNAL] Re: Questions about the trivial downcall
>>
>> Hi, a trivial downcall is supposed to target a native
>> function that (a) terminates quickly (so as not to block the
>> GC for too long) and (b) does not upcall into Java. So, no, a
>> trivial downcall cannot trigger upcalls (I don't think we detect
>>
>> ZjQcmQRYFpfptBannerStart
>>
>> *This Message Is From an External Sender *
>>
>> This message came from outside your organization.
>>
>> * Report Suspicious *
>> <https://us-phishalarm-ewt.proofpoint.com/EWT/v1/PjiDSg!2c-r455VanMQ2qYReaGl7Z4QRx46ATMxAjK9nbXsj13QlLeimn0PtcIAb-U80cJ-A34Q8dYfoQ6JN5nMYOpBz-Hn3cuAGTZLJQ$>
>>
>>
>> ZjQcmQRYFpfptBannerEnd
>>
>> Hi,
>> a trivial downcall is supposed to target a native function
>> that (a) terminates quickly (so as not to block the GC for
>> too long) and (b) does not upcall into Java.
>>
>> So, no, a trivial downcall cannot trigger upcalls (I don't
>> think we detect this, I believe the JVM just crashes if you do).
>>
>> Also I notice that you speak of "JNI" upcall. Is that what
>> you really mean - e.g. a trivial FFM downcall making an
>> upcall using JNI? In general, I think it's a bit hard for
>> downcalls to do anything that has to do with JNI because the
>> invoked native function is not passed a JNIEnv - FFM really
>> just bridges the Java code with the native library function
>> you want to call, nothing more. (I suppose that function
>> could get its hands on the VM using the JNI attach API, but I
>> feel that's a different question from what you were asking?).
>>
>> Maurizio
>>
>> On 26/07/2023 22:23, Cheng Jin wrote:
>>
>> Hi there,
>>
>> I’ve got a couple of questions about the behavior of a
>> trivial downcall (with *isTrivial* specified).
>>
>> Is a FFI downcall able to trigger a JNI upcall ?
>>
>> If so, should a JNI upcall should be captured in this
>> trivial downcall?
>>
>> Best Regards
>>
>> Cheng Jin
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20230727/c83c441c/attachment-0001.htm>
More information about the panama-dev
mailing list