Quality Outreach Heads-up - JDK 24 Prepares Restricted Native Access
Nicolai Parlog on December 9, 2024The OpenJDK Quality Group is promoting the testing of FOSS projects with OpenJDK builds as a way to improve the overall quality of the release. This heads-up is part of a regular communication sent to the projects involved. To learn more about the program, and how-to join, please check here.
Native Access and Integrity by Default
Any interaction between Java code and native code, be it via the Java Native Interface (JNI) or the Foreign Function & Memory API (FFM), is risky in the sense that it can compromise the integrity of applications and of the Java Platform itself, for example by causing JVM crashes, even after the native code completed execution. 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. JDK 24, by means of JEP 472, prepares that by aligning the behavior of JNI and FFM by:
- printing warnings for all restricted operations (with the goal to turn these into exceptions in a future release)
- expanding the command-line options
--enable-native-access
and--illegal-native-access
to govern restricted operations of both APIs
Note that the intent is neither to discourage the use of, deprecate, or even remove JNI nor to restrict the behavior of native code called via JNI or FFM. The goal is to ensure that applications and the Java Platform have integrity by default while giving application operators the tools they need to selectively opt-out where needed.
Restricted Operations
These JNI operations are considered restricted:
- calls to
System::loadLibrary
,System::load
,Runtime::loadLibrary
, andRuntime::load
- declaration of a native method
These FFM operations are considered restricted:
AddressLayout::withTargetLayout
Linker::downcallHandle
Linker::upcallStub
MemorySegment::reinterpret
ModuleLayer.Controller::enableNativeAccess
SymbolLookup::libraryLookup
The documentation contains an always up-to-date list of all restricted methods.
Enabling/Disabling Restricted Operations
Executing restricted operations will, by default, cause output like the following on the standard error stream:
WARNING: A restricted method in java.lang.System has been called
WARNING: System::load has been called by com.foo.Server in module com.foo (file:/path/to/com.foo.jar)
WARNING: Use --enable-native-access=com.foo to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
Note that this is a change for JNI, which used to not trigger such warnings, as well as for FFM, which used to forbid restricted operations by default.
Starting with JDK 24, both APIs behave uniformly by printing warnings - in the future, both will throw exceptions instead.
You can configure this behavior with the two command line options --enable-native-access
and --illegal-native-access
.
The option --enable-native-access=$value
enables access to all restricted operations for either the entire class path (if $value
is ALL-UNNAMED
) or the listed modules (if $value
is similar to com.mod1,com.mod2
).
This is the intended and long-term supported way to enable access to restricted native operations.
If native access is not enabled via that option, it is illegal for code to perform restricted operations.
The new option --illegal-native-access=$value
determines how the Java runtime handles such cases, depending on $value
:
allow
: allows the operationwarn
: issues warnings as described above (this is the default in JDK 24)deny
: throws anIllegalCallerException
In a future release, deny
will become the default and allow
will be removed.
Similar to --illegal-access
, which was introduced in JDK 9, setting this option to values below the default (e.g. to allow
on JDK 24) should be considered a short-term fix until the correct use of --enable-native-access
is established.
Also similar to --illegal-access
, --illegal-native-access
can be used to prepare a project for a future, stricter Java release.
The recommended way to run applications that use JNI or FFM on JDK 24 is:
java --enable-native-access=$value --illegal-native-access=deny ...
Here, $value
is ideally a list of names of modules that access restricted operations, otherwise ALL-UNNAMED
if such code resides on the class path.
More
To help identify libraries that use JNI, a new JDK tool, tentatively named jnativescan
, statically scans code in a provided module path or class path and reports uses of restricted methods and declarations of native methods.
If you want to track (un)loading of native libraries, observe the JDK Flight Recorder events jdk.NativeLibraryLoad
and jdk.NativeLibraryUnload
.
For more details, please read JEP 472 and check JDK-8324665.