<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>