-
CSR
-
Resolution: Approved
-
P4
-
None
-
low
-
-
Java API, add/remove/modify command line option
-
SE
Summary
Issue warnings about uses of the Java Native Interface (JNI). 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. 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) 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, all JDK features that are capable of breaking integrity must obtain explicit approval from the application's developer.
Solution
The FFM API restricts 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 <code class="prettyprint" data-shared-secret="1741789161015-0.6837757797757866">ModuleLayer.Controller::enableNativeAccess</code> method, which is itself a restricted method.
The JNI Invocation API 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.
Code can test, at runtime, whether or not its module has native access enabled with the method Module.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 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 anIllegalCallerException
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 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 <code class="prettyprint" data-shared-secret="1741789161015-0.6837757797757866">load</code> and <code class="prettyprint" data-shared-secret="1741789161015-0.6837757797757866">loadLibrary</code> methods of the java.lang.Runtime
class.
(The identically named convenience methods <code class="prettyprint" data-shared-secret="1741789161015-0.6837757797757866">load</code> and <code class="prettyprint" data-shared-secret="1741789161015-0.6837757797757866">loadLibrary</code> 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 the native
method. (The correspondence between the native
method and the native code is described here.)
Binding a native method is a restricted operation, just as obtaining a downcall handle via the FFM API’s <code class="prettyprint" data-shared-secret="1741789161015-0.6837757797757866">Linker::downcallHandle</code> 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 thenative
method is called. The warning is not issued every time that thenative
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
andjdk.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 declaringnative
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.
- csr of
-
JDK-8331671 Implement JEP 472: Prepare to Restrict the Use of JNI
-
- Resolved
-
- relates to
-
JDK-8338596 Clarify handling of restricted and caller-sensitive methods
-
- Resolved
-
-
JDK-8334569 Add a tool like jdeprscan to find usage of restricted methods
-
- Closed
-
-
JDK-8346778 Enable native access should work with the source launcher
-
- Resolved
-
- links to