JDK-8331672 : Implement JEP 472: Prepare to Restrict the Use of JNI
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang.foreign
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 24
  • Submitted: 2024-05-03
  • Updated: 2024-08-23
  • Resolved: 2024-08-23
Related Reports
CSR :  
Relates :  
Relates :  
Description
Summary
-------

Issue warnings about uses of the [Java Native Interface (JNI)](https://docs.oracle.com/en/java/javase/22/docs/specs/jni/index.html). These warnings aim to prepare developers for a future release that restricts the use of JNI by default in order to improve [integrity by default](https://openjdk.org/jeps/8305968). The warnings issued in this release, and the exceptions thrown in that future release, can be avoided by selectively enabling native access. Adjust the Foreign Function & Memory API ([JEP 454](https://openjdk.org/jeps/454)) to issue warnings in a consistent manner.

Problem
-------

Any interaction at all between Java code and native code is risky because it can compromise the integrity of applications and of the Java Platform itself. According to the policy of [integrity by default](https://openjdk.org/jeps/8305968), all JDK features that are capable of breaking integrity must obtain explicit approval from the application's developer.

Solution
--------

The FFM API [restricts](https://openjdk.org/jeps/454#Safety) the ability to load native libraries and to obtain method handles for native code; it does not restrict the ability to call native code. We propose here to do the same for JNI, by restricting the loading of native libraries and the binding of `native` methods; we will not restrict the calling of native methods. As with the FFM API, these restrictions can be lifted for specific modules by enabling native access for those modules. We will strengthen the effects of the restrictions over time, starting with warnings and proceeding gradually to unavoidable exceptions.

Specification
-------------

### Enabling native access

You can lift the native-access restrictions for selected modules, in effect acknowledging your application's need to load native libraries and bind `native` methods, in the same way as for the FFM API. At startup, use the command line option

```
$ java --enable-native-access=M,... ...
```

where `M,...` is a comma-separated list of modules that should be allowed to perform restricted operations. To lift restrictions on code on the class path, use

```
$ java --enable-native-access=ALL-UNNAMED ...
```

As an alternative to the `--enable-native-access` option, you can add this attribute to the manifest of an executable JAR file, i.e., a JAR file that is launched via the `java -jar` option:

```
Enable-Native-Access: ALL-UNNAMED
```

`ALL-UNNAMED` is the only supported value; other module names cause an exception to be thrown.

When a module is created programmatically, you can enable native access for it via the [`ModuleLayer.Controller::enableNativeAccess`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/ModuleLayer.Controller.html#enableNativeAccess(java.lang.Module)) method, which is itself a restricted method.

The [JNI Invocation API](https://docs.oracle.com/en/java/javase/22/docs/specs/jni/invocation.html) allows a native application to embed a JVM in its own process. A native application which uses the JNI Invocation API can enable native access for modules in the embedded JVM by passing the `--enable-native-access` option when [creating the JVM](https://docs.oracle.com/en/java/javase/22/docs/specs/jni/invocation.html#jni_createjavavm).

Code can test, at runtime, whether or not its module has native access enabled with the method [Module.isNativeAccessEnabled](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/Module.html#isNativeAccessEnabled()).

### Controlling the consequences of illegal native access

Performing a restricted operation in a module that does not have native access is deemed illegal. What action the Java runtime takes when such an operation is attempted is controlled by a new command line option, `--illegal-native-access`, which is similar in spirit and form to the `--illegal-access` option introduced by [JEP 261](https://openjdk.org/jeps/261#Relaxed-strong-encapsulation) in JDK 9. It works as follows:

  - `--illegal-native-access=allow` allows the operation to proceed.

  - `--illegal-native-access=warn` allows the operation but issues a warning the first time that illegal native access occurs in a particular module. At most one warning per module is issued.

    This mode is the default in JDK 24. It will be phased out in a future release and, eventually, removed.

  - `--illegal-native-access=deny` throws an `IllegalCallerException` exception for every illegal native access operation.

    This mode will become the default in a future release.

When `deny` becomes the default mode then `allow` will be removed but `warn` will remain supported for at least one release.

### Aligning the FFM API

In prior releases, if one or more modules were granted native access via the `--enable-native-access` option then attempts to call [restricted FFM methods](https://openjdk.org/jeps/454#Safety) from any other module would cause an `IllegalCallerException` to be thrown.

To align the FFM API with JNI, we will relax this behavior so that illegal native access operations are treated exactly the same by the FFM API as in JNI. This means that, in JDK NN, such operations will result in warnings rather than exceptions.

Applications currently using the FFM API can get the old behavior with this combination of  options:

```
$ java --enable-native-access=M,... --illegal-native-access=deny
```

### Warnings on loading native libraries

Native libraries are loaded via the [`load`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/Runtime.html#load(java.lang.String)) and [`loadLibrary`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/Runtime.html#loadLibrary(java.lang.String)) methods of the `java.lang.Runtime` class.
(The identically named convenience methods [`load`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/System.html#load(java.lang.String)) and [`loadLibrary`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/System.html#loadLibrary(java.lang.String)) of the `java.lang.System` class merely invoke the corresponding methods of the system-wide `Runtime` instance.)

The methods `java.lang.Runtime.load`, `java.lang.System.load`,  `java.lang.Runtime.loadLibrary`, and `java.lang.System.loadLibrary` are annotated with `@Restricted`.

When a restricted method is called from a module that has not been granted native access via the `--enable-native-access` option, the JVM runs the method but, by default, issues a warning that identifies the caller:

```
WARNING: A restricted method in java.lang.System has been called
WARNING: System::load has been called by com.foo.Server in an unnamed module (file:/path/to/comfoo.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
```

The warning is written to the standard error stream. At most one such warning is issued for any particular module, and only if a native-access warning has not yet been issued for that module. (The _unnamed module_, mentioned in this example warning, is the module containing code on the class path.)


### Warnings on binding `native` methods

When a `native` method in Java code is first called, the method is linked to the corresponding native code in a native library. This operation is called [_binding_](https://docs.oracle.com/javase/specs/jvms/se22/html/jvms-5.html#jvms-5.6) the `native` method. (The correspondence between the `native` method and the native code is described [here](https://docs.oracle.com/en/java/javase/22/docs/specs/jni/design.html#resolving-native-method-names).)

Binding a native method is a restricted operation, just as obtaining a downcall handle via the FFM API’s [`Linker::downcallHandle`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/foreign/Linker.html#downcallHandle(java.lang.foreign.MemorySegment,java.lang.foreign.FunctionDescriptor,java.lang.foreign.Linker.Option...)) method is restricted. When a `native` method is bound in  a module that has not been granted native access via the `--enable-native-access` option, the JVM binds the method but, by default, issues a warning that identifies the caller:

```
WARNING: A restricted method in java.lang.System has been called
WARNING: System::load has been called by com.foo.Server is declared in module foomod (file:/path/to/comfoo.jar)
WARNING: Use --enable-native-access=foomod to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
```

At most one such warning is issued for any particular module. Specifically:

- The warning is issued only when a `native` method is bound, which happens the first time that the `native` method is called. The warning is not issued every time that the `native` method is called.

- The warning is issued the first time that any `native` method declared in a particular module is bound, unless a native-access warning has already been issued for that module.

## Identifying the use of native code

- The JFR events `jdk.NativeLibraryLoad` and `jdk.NativeLibraryUnload` track the loading and unloading of native libraries.

- To help identify libraries that use JNI, a new JDK tool, `jnativescan`, statically scans code in a provided module/class path and reports use of restricted methods as well as classes declaring `native` methods. The tool is described in the CSR JDK-8334569.

## Documentation

- Javadoc diff: https://cr.openjdk.org/~mcimadamore/jdk/8331671/v1/specdiff_out/
- Man page: https://github.com/openjdk/jdk-sandbox/blob/58fca7e89f52deb47c6d320f0193f996b6024b47/src/java.base/share/man/java.1#L551

## Man page diff

```
\f[V]--enable-native-access\f[R] \f[I]module\f[R][\f[V],\f[R]\f[I]module\f[R]...]
Native access involves access to code or data outside the Java runtime.
This is generally unsafe and, if done incorrectly, might crash the JVM
or result in memory corruption.
Native access can occur as a result of calling a method that is either
\f[B]restricted\f[R] [https://openjdk.org/jeps/454#Safety], or
\f[V]native\f[R].
This option allows code in the specified modules to perform native
access.
Native access occurring in a module that has not been explicitly enabled
is deemed \f[I]illegal\f[R].
.RS
.PP
\f[I]module\f[R] can be a module name, or \f[V]ALL-UNNAMED\f[R] to
indicate code on the class path.
.RE
.TP
-\f[V]--illegal-native-access=\f[R]\f[I]parameter\f[R]
This option specifies a mode for how illegal native access is handled:
.RS
.RS
.PP
\f[B]Note:\f[R] This option will be removed in a future release.
.RE
.IP \[bu] 2
\f[V]allow\f[R]: This mode allows illegal native access in all modules,
without any warings.
.IP \[bu] 2
\f[V]warn\f[R]: This mode is identical to \f[V]allow\f[R] except that a
warning message is issued for the first illegal native access found in a
module.
This mode is the default for the current JDK but will change in a future
release.
.IP \[bu] 2
\f[V]deny\f[R]: This mode disables all illegal native access except for
those modules enabled by the \f[V]--enable-native-access\f[R]
command-line option.
That is, any illegal native access causes an
\f[V]IllegalCallerException\f[R].
This mode will become the default in a future release.
.PP
To verify that your application is ready for a future version of the
JDK, run it with \f[V]--illegal-native-access=deny\f[R] along with any
necessary \f[V]--enable-native-access\f[R] options.
```
Comments
Moving to Approved.
23-08-2024

Thanks [~dholmes] for the review comments. Moving this CSR to Provisional. Based on the comments in this CSR, I've filed JDK-8338596 with a fixVersion of 24 to capture the changes needed to more clearly specify how restricted and caller-sensitive methods are handled.
19-08-2024

I have uploaded the requested changes to the JNI spec: 1. The changes to Chapter 1 requested by [~darcy] 2. Dropping the word "small" from "a small number of methods" in Chapter 2, as requested by [~dholmes]. As for the matter of better documenting restricted methods (and other caller-sensitive methods in general), the plan is as follows: 1. Move the restricted method section to a separate page 2. Link to that section from all restricted methods, using some javadoc work. 3. Generalize and improve that section, by adding a note re. what happens when restricted methods are called from JNI or upcalls. 4. Gradually review other caller-sensitive methods and enhance their documentation. As this work pertains to matters unaffected by JEP 472, as well as for logistical reasons, I suggest it should be done separately and tracked in other JBS issues.
15-08-2024

I think each method that is restricted and/or caller-sensitive should specify what happens when called when there is no caller context. We should use AccessibleObject::canAccess as an exemplar here: https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/reflect/AccessibleObject.html#canAccess(java.lang.Object) I have no doubt other caller-sensitive methods have failed to do this to date, but that should be fixed.
15-08-2024

A quick point on logistics, with the `##` syntax support in javadoc to link to define anchors with `@see` and `@link` tags, I've found the pattern of: * Writing a shared block of text explaining something * Linking to it from throughout a package, etc. to be more tractable than before This can include adding text in a package-info file.
14-08-2024

Some more notes. There is a section on restricted methods on java.lang.foreign package-info. [~rpressler] has suggested to move that to java.base. That section starts with: ``` Some methods in this package are considered <em>restricted</em>. Restricted methods are typically used to bind native foreign data and/or functions to first-class Java API elements which can then be used directly by clients ... ``` Which feels a bit FFM-centric to me. There is a related "implementation note" which says ``` @implNote In the reference implementation, access to restricted methods can be granted to specific modules using the command line option {@code --enable-native-access=M1,M2, ... Mn} ... ``` This should probably be moved wherever the previous section is moved. Last, I've checked some caller sensitive methods in the JDK, and they seem to generally fail to specify what happens in corner cases (e.g. when upcalled from a native thread from JNI). For instance, consider this: https://docs.oracle.com/en%2Fjava%2Fjavase%2F22%2Fdocs%2Fapi%2F%2F/java.base/java/util/ResourceBundle.html#getBundle(java.lang.String) I can't (easily) see (a) whether this method is caller sensitive (well, that can be inferred maybe from the fact that the javadoc speaks of "caller module"). And (b) what is "caller module" when JNI is in play. IMHO, an implementation note should be added to all caller sensitive methods in the JDK to specify their already existing behavior (and this includes restricted methods). My feeling is that such an effort would be big, as there are several caller sensitive, each one adopting different policies for when no caller module/class exists. That said, if we limit this exercise to restricted methods, it should be a bit better, since _all_ restricted methods share the same policy, which we can document. It would be helpful to understand what of the above should be fixed as part of this CSR, and what can be deferred to a later follow up PR/CSR. Thanks.
14-08-2024

[~mcimadamore] I think that the section on restricted methods should be moved to the Javadoc of java.base. Additionally, we could add something about caller-sensitivity (and restricted methods in particular) to the Javadoc of `upcallStub`.
14-08-2024

[~dholmes] > but AFAICS these new restricted methods (e.g. System.loadLibrary) do not identify themselves as "caller sensitive" nor do they define what happens if called with no Java frames on the stack. So how does the programmer determine this? ( Did the restricted methods already added in 22 address this?) While the implementation for the restricted method check will correctly handle the case of a call coming from a thread with no Java frames underneath (the call is treated as if coming from the unnamed module), it is true that the javadoc of restricted methods don't say anything in this regard. Since this is not the first time this comes up, we should perhaps add a clarifying note somewhere. Question is: where? Some options: * platform spec. Maybe correct, but not very discoverable. * package-level section on restricted method in the FFM javadoc. This looks like a good compromise. Except that, now that `System::loadLibrary` is not in `java.lang.foreign`, one might wonder if that section is even in the right place. * say something in each of the 8-9 restricted methods. This feels a bit of a copy/paste exercise, and I can imagine us forgetting to do this if we add new restricted methods. * the JNI spec. Not a bad idea. But JNI is not the only way to call a restricted method from a Java-less thread. You can achieve the same by creating an upcall handle with FFM from a restricted methods, pass the handle as a function pointer to C code, and have the C code spawn some new threads and call the function pointer (this is all tested). Any preference/guidance?
14-08-2024

With regards to the JNI spec changes ... We are saying that restricted methods are caller-sensitive methods, and then appeal to the existing specification text around caller-sensitive methods that: "it is up to the author of JNI code to determine whether a method called by JNI is caller-sensitive and may behave differently when called through JNI" but AFAICS these new restricted methods (e.g. `System.loadLibrary`) do not identify themselves as "caller sensitive" nor do they define what happens if called with no Java frames on the stack. So how does the programmer determine this? ( Did the restricted methods already added in 22 address this?) It seems to me that a native application that wants to perform per-module native-access control would have to be rewritten to do away with any natively attached threads (with no Java frames when making upcalls) and switch to a model where threads are only created from Java and then call down to native code to do what those threads would normally do (or else introduce a special upcall that then performs the same kind of downcall) to ensure at least on Java frame is always present. This is just an observation that we may want to provide some guidance to the developers of such applications. Looking at: ``` @@ -473,8 +485,9 @@ implemented internally. A small number of Java methods have a special property called caller sensitivity. A _caller-sensitive_ method can behave differently depending on the identity of its immediate caller. -For example, [AccessibleObject::canAccess](../../api/java.base/java/lang/reflect/AccessibleObject.html#canAccess(java.lang.Object)) -needs to know the caller to determine accessibility. +For example, [`AccessibleObject.canAccess`](../../api/java.base/java/lang/reflect/AccessibleObject.html#canAccess(java.lang.Object)) +needs to know the caller to determine accessibility. All *restricted methods*, +specified by the Java SE Platform Specification, are also caller-sensitive. ``` we may want to drop "small" from the first sentence.
13-08-2024

Moving back to Provisional, not Approved. [~rpressler], I read over the JEP and CSR again. I think the JNI spec updates need a bit more refinement before the CSR can be Approved. In particular, please update in the JNI spec "Chapter 1: Introduction" through an integrity by default lens. (The whole section would benefit from a large re-write, but a general update is *not* need for this CSR.) I think the main points to convey in section 1 include: - native libraries might not be loadable - FFM, VarHandles, MethodHandles, etc. cover many use-cases JNI was historically used for The JNI Spec is not super easy to navigate to, but it is much more discoverable than the portions of the Platform Spec mentioned in : https://bugs.openjdk.org/browse/JDK-8331672?focusedId=14693930&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-14693930
13-08-2024

[~iris] Here is a draft of changes for the Platform Spec "Restricted methods". Before "An Implementation may provide a means ...", insert this text, which mirrors earlier text in the section: ----- In addition, `native` methods can cause arbitrary undefined behavior, including JVM crashes. Such problems cannot be prevented by the Java runtime, nor do they provoke exceptions for Java code to catch. Given the potential danger of `native` methods, the following rule applies: - An Implementation must issue a warning on the standard error stream every time a `native` method is bound, unless (1) the method is declared in a class in the java.base module, or (2) the method is declared in a class in a module identified previously to ModuleLayer.Controller.enableNativeAccess, or (3) as provided for below. ----- Then: ----- An Implementation may provide a means to invoke its run-time system with (1) all restricted methods treated as unrestricted when invoked from code identified to the run-time system, and (2) `native` methods treated as if they are already bound if declared in code identified to the run-time system. If the run-time system is invoked in this way, then by definition there are no restricted methods for the identified code to invoke, and no `native` methods in the identified code that are not bound. Therefore, no warnings are issued during the execution of such code. If code other than that identified to the run-time system either invokes a restricted method or declares a `native` method that is bound, the Implementation may give a signal other than a warning issued on the standard error stream. ----- This is not the full set of changes. I respectfully request that the editor of the Platform Specification fills in the following blanks: - Changes to "(The Reference Implementation provides ..." to account for warnings about binding `native` methods. - Corrections to the frequency of warnings, so that the Spec and RI are aligned. This applies whether the warning is for invoking a restricted method or binding a `native` method.
31-07-2024

JNI spec updated
31-07-2024

[~rpressler] Re: JNI Spec ch.2 "Compiling, Loading and Linking Native Methods": - Put the new paragraph about System.loadLibrary et al before the paragraph about "Support for both dynamically and statically linked libraries..." Here is a modified version of that new paragraph, with revision indicators inline: "The method `System.loadLibrary` and the ***related methods*** `System.load`, `System.***mapLibraryName***`, `Runtime.loadLibrary`, and `Runtime.load` are *restricted*: their behavior depends on whether the module of their caller has native access enabled, determined as if invocation of `Module.isNativeAccessEnabled`. +++For more information about restricted methods, see the Java SE Platform Specification and [Calling Caller-Sensitive Methods]...+++" "Resolving Native Method Names": - Opening paragraph: "... The VM uses this mapping to dynamically link a Java invocation of a native method to the corresponding implementation in the native library. +++This linking operation is *restricted*: its outcome depends on whether the module of the class that declares the `native` method has native access enabled, determined as if by invocation of Module.isNativeAccessEnabled.+++" Also, later: The explicit linking of a native method with `RegisterNatives` is not affected by whether native access is enabled for any module.
31-07-2024

- I’ve added the JNI spec diff, which changes Chapter 2 to say the following: 1. `System.loadLibrary` (et al.) is restricted. 2. Implicitly linking a native method is restricted. 3. Explicitly linking a native method with `RegisterNatives` is not restricted. 4. All restricted methods are caller-sensitive (the specification already says that it is up to the author of JNI code to determine whether a method called by JNI is caller-sensitive and may behave differently when called through JNI). - I’ve attached the API spec diff - This JEP makes no changes to JDK APIs. - Other changes to the platform specification need to be done regarding the case of a restricted method called without a Java frame, but these cases are not affected by this JEP. [~abuckley]: Caller-sensitivity is covered in Chapter 2, where I’ve added a mention of restricted method, so there’s no need to change Chapter 4. As for Chapter 5, in the specification of `JNI_CreateJavaVM`, the options passed as a`vm_args` argument are specified as “option strings to encode arbitrary VM start up options”. The `java` launcher specifies what these options are. The only options mentioned in this section are those whose form may differ from that accepted by `java`. Is there a need to single out `--enable-native-access`? If so, how?
31-07-2024

> A particular question: if JNI upcalls to System.loadLibrary(), what are the intended semantics in terms of what module context is present, if any? While it's true that either the platform spec, or the JNI spec, or the FFM API javadoc (in its package info file) should say something about this case, please note that this is not a new condition that arises as part of this CSR. Restricted methods have been with us since Java 22, and it has always been possible to call them from JNI upcalls. When that happens, if we have a Java caller class, we'll use that (and its module) to perform the required restricted method checks. If such a class doesn't exist (e.g. because the upcall comes from a new native thread w/o any Java frames underneath), we treat the call as coming from the unnamed module, as said by [~alanb].
31-07-2024

> A particular question: if JNI upcalls to System.loadLibrary(), what are the intended semantics in terms of what module context is present, if any? This isn't different to any other caller sensitive methods that are invoked from JNI (or through a native frame), "caller" is the always the Java caller. The corner case that comes up (mentioned in several CSRs) is where a JNI attached thread invokes a caller sensitive method with no caller frames on the stack. We've treated these cases (eg. AccessibleObject) as if the caller is an unnamed module.
31-07-2024

> error stream every time a native method is bound I believe the rule is that the warning is issued only the first time a restricted operation is performed in a module, where "restricted operation in module M" is either a call to a restricted method from a caller in module M or the binding of a native method declared in a class in module M.
30-07-2024

The Java SE Platform Specification has a section "Restricted methods" (https://cr.openjdk.org/~iris/se/23/latestSpec/index.html#Restricted-methods). Since binding a `native` method is intended to be a restricted operation, the Platform Spec for SE 24 could (as one possible approach) say that all `native` methods are restricted (and this would hold even though `native` methods are not listed in the "Restricted Methods" section of the API Specification).
30-07-2024

I agree with [~darcy] that the JNI Specification should reflect the fact that calling native code from Java code is now restricted. The relevant sections are in ch.2: - "Compiling, Loading and Linking Native Methods" (System.loadLibrary et al are restricted methods.) - "Resolving Native Method Names" (Binding a `native` method is now a restricted operation.) Calling Java code (and into the VM) from native code is also affected: - Ch.4: What happens when native code invokes *any* restricted operation? - Ch.5, "Creating the VM" (Can pass `--enable-native-access`)
30-07-2024

[~darcy] > if JNI upcalls to System.loadLibrary(), what are the intended semantics in terms of what module context is present, if any? That's a good question that applies to all calls to restricted methods (and to all caller-sensitive operations in general). The caller-sensitive [`MethodHandles.lookup`](https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/invoke/MethodHandles.html#lookup()) method says: > In cases where MethodHandles.lookup is called from a context where there is no caller frame on the stack (e.g. when called directly from a JNI attached thread), IllegalCallerException is thrown I think that the platform spec for restricted methods that Alex linked to would need to say something similar.
30-07-2024

[~abuckley] That binding a `native` method is restricted does not imply that `native` methods are restricted methods. Restricted methods are blocked or not depending on their caller; `native` methods are blocked or not depending on their declaring class. Unlike for a restricted method, the caller of a `native` method needs no special permission.
30-07-2024

After another round of review, moving to Provisional, not Approved. Given the impact of the usage of JNI, I think it would be appropriate for the JNI specification to have some kind of update associated with this effort. A particular question: if JNI upcalls to System.loadLibrary(), what are the intended semantics in terms of what module context is present, if any? (The PR may already handle this situation, but from a quick skim I didn't see it.) Please clarify which non-API portions of this CSR are for JDK interfaces vs Java SE interfaces. For example, the Jar manifest handling is currently defined to be JDK-specific rather than required in SE: https://download.java.net/java/early_access/jdk24/docs/specs/jar/jar.html
30-07-2024

Moving to Provisional.
13-06-2024

[~rpressler], please fill in the "Compatibility Risk Description" field and attach or inline some presentation of the man page changes and API updates.
24-05-2024

Setting the scope to "SE" for adding the ability to effectively disable JNI, a required part of the platform.
09-05-2024