<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p><br>
</p>
<div class="moz-cite-prefix">On 29/08/2023 23:07, CC wrote:<br>
</div>
<blockquote type="cite" cite="mid:CADRZvh4r2c_G9j214hyRsWCa-M+4qs_GeBEFa+0P9tCYnCPvuQ@mail.gmail.com">
<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" moz-do-not-send="true" class="moz-txt-link-freetext">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>
</div>
</blockquote>
I believe this document (which has been shared several times):<br>
<p><a class="moz-txt-link-freetext" href="https://openjdk.org/jeps/8305968">https://openjdk.org/jeps/8305968</a></p>
<p>Covers all the bases you touch upon.<br>
</p>
<blockquote type="cite" cite="mid:CADRZvh4r2c_G9j214hyRsWCa-M+4qs_GeBEFa+0P9tCYnCPvuQ@mail.gmail.com">
<div dir="ltr">
<div dir="ltr">
<div><br>
</div>
<div>> Calling native code can lead to arbitrary <a href="https://en.wikipedia.org/wiki/Undefined_behavior" moz-do-not-send="true">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>
</div>
</blockquote>
Unsafe is covered in the document above. I don't know what you mean
by "misconfigured method handles".<br>
<blockquote type="cite" cite="mid:CADRZvh4r2c_G9j214hyRsWCa-M+4qs_GeBEFa+0P9tCYnCPvuQ@mail.gmail.com">
<div dir="ltr">
<div dir="ltr">
<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" moz-do-not-send="true">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>
</div>
</blockquote>
<p>This is incorrect. As documented in the FFM API JEP:</p>
<p><a class="moz-txt-link-freetext" href="https://openjdk.org/jeps/442">https://openjdk.org/jeps/442</a></p>
<p>certain functionalities of the FFM API are provided as
"restricted methods" which feature similar restrictions as the
ones Ron is proposing for JNI (disabled by default, enabled with
flag). The JEP draft Ron pointed at even contains a mapping
between FFM restrictions and proposed JNI restrictions, so it
should be fairly evident that FFM is restricted exactly in the
same way proposed for JNI (and has been for the last 2 years).<br>
</p>
<blockquote type="cite" cite="mid:CADRZvh4r2c_G9j214hyRsWCa-M+4qs_GeBEFa+0P9tCYnCPvuQ@mail.gmail.com">
<div dir="ltr">
<div dir="ltr">
<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" moz-do-not-send="true">access fields</a> and <a href="https://docs.oracle.com/en/java/javase/20/docs/specs/jni/functions.html#calling-instance-methods" moz-do-not-send="true">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>
</div>
</blockquote>
<p>Here I completely disagree. While I can understand why you might
think that way - you are almost certainly underestimating the cost
that is associated with "changing internal fields [...] to make
something work the way you want".</p>
<p>I suggest you take a look at this:</p>
<p><a class="moz-txt-link-freetext" href="https://bugs.openjdk.org/browse/JDK-8233873">https://bugs.openjdk.org/browse/JDK-8233873</a></p>
<p>And see how much difficult it is for the JIT to do something that
looks fairly trivial (constant folding of a final field) simply
because it has to be conservative of the many ways in which a
final field can be mutated (even if that's of course not allowed
on paper).</p>
<p>And then there's forward-compatibility. If every Java
application/library out there had free access to every JDK
internal, that would mean that either (a) such
applications/libraries would need significant updates on each JDK
release or (b) that the implementation of the JDK stagnates to
make sure that none of these applications/libraries will break
ever. Needless to say, both outcomes are rather sad.</p>
<p>But we're digressing - while JNI *can* be used to escape from
access checks, I actually think that most developers resorting to
JNI do that because they need to access some functionality that is
not provided by the JDK. Note how this is also one of the driving
use cases of the new FFM API. That said, even though FFM can't
mutate final fields (unlike JNI), it is still important to
acknowledge the fact that it's not just an ordinary Java API. The
functionalies it provides are powerful but, if misused, can lead
to very bad situations (JVM crashes, memory corruption, you name
it). And, as you say, since this can all be done "from the comfort
of java" there has to be some way for the JDK to say that not all
its API methods are created equal. We can quibble about the
specifics of the mechanism we pick to do this - but I hope we
agree that unleashing FFM API w/o any kind of opt-in for some of
its unsafest corners would *not* be a great thing for the wider
Java ecosystem.<br>
</p>
<p>Maurizio<br>
</p>
<p><br>
</p>
</body>
</html>