<div dir="ltr"><div dir="ltr"><div>I've looked through the JEP a bit more, and can confidently say that this will be the first step towards a future I, personally, would not want to live in regarding java.</div><div><br></div><div>> Unfortunately, any interaction <em>at all</em> between Java code and
native code is risky because /it can compromise the integrity of
applications and the Java Platform itself/. According to the policy of
(<a href="https://openjdk.org/jeps/8305968">https://openjdk.org/jeps/8305968</a>), all JDK features that are capable of
breaking integrity must obtain explicit approval from the end user or
the application assembler.<br></div><div><br></div><div>So what about reflection? Method handles? Accessing even just the smallest of internals? Unsafe? All of those could compromise the integrity of the java platform, and should therefore be locked behind the library user accepting them to be used. Why aren't they locked behind flags?</div><div><br></div><div>> Calling native code can lead to arbitrary <a href="https://en.wikipedia.org/wiki/Undefined_behavior">undefined behavior</a>, including JVM crashes. Such problems cannot be prevented by the Java runtime or caught by Java code.<br></div><div>Unsafe. Misconfigured method handles.<br></div><div><br></div><div>> Native code and Java code often exchange data through <a href="https://docs.oracle.com/en/java/javase/20/docs/specs/jni/functions.html#newdirectbytebuffer">byte buffers</a>,
which are regions of memory not managed by the JVM's garbage collector.
Native code can produce a byte buffer that is backed by an invalid
region of memory, and using the byte buffer in Java code is practically
certain to cause undefined behavior.</div><div>The foreign memory API will allow you to do that directly from the comfort of java.</div><div><br></div><div>> Native code could use the JNI API to <a href="https://docs.oracle.com/en/java/javase/20/docs/specs/jni/functions.html#accessing-fields-of-objects">access fields</a> and <a href="https://docs.oracle.com/en/java/javase/20/docs/specs/jni/functions.html#calling-instance-methods">call methods</a> without any access checks by the JVM or even change the values of <code>final</code>
fields long after they are initialized because the implementation of
JNI does not perform the appropriate checks. Java code that uses JNI
could therefore circumvent any of the invariants established through
strong encapsulation of any other Java code.</div><div>So what? There are legitimate reasons for this, changing internal fields may sometimes be required to make something work the way you want. There is no reason to use this as an argument against JNI, because it legitimately is a good use case. While I agree that changing a String instance's data array would be a bit silly, that example is also about the least practical example of this.</div><div><br></div><div>> Native code which uses certain functions of the JNI API incorrectly (principally <a href="https://docs.oracle.com/en/java/javase/20/docs/specs/jni/functions.html#getprimitivearraycritical-releaseprimitivearraycritical"><code>GetPrimitiveArrayCritical</code></a> and <a href="https://docs.oracle.com/en/java/javase/20/docs/specs/jni/functions.html#getstringcritical-releasestringcritical"><code>GetStringCritical</code></a>) may cause <a href="https://shipilev.net/jvm/anatomy-quarks/9-jni-critical-gclocker/">undesirable behavior by the garbage collector</a> that can manifest at any time during the program's lifetime.</div><div>This can be said about a lot of other things as well; A feature is not at fault for a bad programmer using it.</div><div><br></div><div>Other arguments in this thread are so extremely out of touch with how the modern java world works, they have me questioning the timeline I am living in.</div><div><br></div><div>This thread is a prideful demonstration of the sheer incompetence managing the Java specification, and I am ashamed even being apart of it.</div><div><br></div><div>This will be my final message on the topic, lest these changes run into the danger of being merged.</div><div><br></div><div>Constantin<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Am Di., 29. Aug. 2023 um 18:16 Uhr schrieb Alex Buckley <<a href="mailto:alex.buckley@oracle.com">alex.buckley@oracle.com</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 8/29/2023 8:47 AM, Quân Anh Mai wrote:<br>
> There is a huge difference between --add-opens and <br>
> --enable-native-access here. While the sole purpose of --add-opens is to <br>
> break encapsulation and open implementation details, dependence on which <br>
> is a major factor causing the friction of migration from 8 to 9, the <br>
> purpose of JNI is not to break anything, but to simply enable native <br>
> accesses from Java. While encapsulation breakage is possible in JNI, <br>
> equating it as its sole purpose seems illogical. As a result, forcing <br>
> the users to treat it similarly as --add-opens and friends seems not to <br>
> be reasonable to me.<br>
<br>
We are not saying that breaking encapsulation is the sole purpose of <br>
JNI. We are saying that the use of native code, while sometimes the only <br>
way to do something, is risky. The JEP identifies four risks -- <br>
<a href="https://openjdk.org/jeps/8307341#Motivation" rel="noreferrer" target="_blank">https://openjdk.org/jeps/8307341#Motivation</a> -- of which the first two -- <br>
undefined behavior and bad buffers -- are by far the worst.<br>
<br>
We are then saying something further: the risks are so high that the <br>
user should explicitly agree to take them.<br>
<br>
Alex<br>
</blockquote></div></div>