Skip to content

Commit 32b955d

Browse files
committed
fix: Skip JNI native access check on JDK < 24 (fixes #1689)
Module.isNativeAccessEnabled() was backported to some JDK 21 builds (e.g. 21.0.10), causing a false UnsupportedOperationException since the method returns false even though JNI works without --enable-native-access. JNI native access restrictions are only enforced from JDK 24+, so skip the check on earlier versions.
1 parent 066befe commit 32b955d

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

terminal-jni/src/main/java/org/jline/terminal/impl/jni/JniTerminalProvider.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,26 @@ public JniTerminalProvider() {
7171

7272
/**
7373
* Checks that native access is enabled for this module.
74-
* Uses reflection because {@code Module.isNativeAccessEnabled()} is only available on JDK 22+
75-
* and {@code Class.getModule()} is only available on JDK 9+.
76-
* On older JDKs, the check is skipped (no restrictions exist).
74+
* JNI native access restrictions are only enforced from JDK 24+, so the check
75+
* is skipped on earlier versions. Uses reflection because
76+
* {@code Module.isNativeAccessEnabled()} is not available on all JDK versions.
7777
*
7878
* @throws UnsupportedOperationException if native access is not enabled
7979
*/
8080
static void checkNativeAccess() {
81+
// JNI native access restrictions are only enforced starting from JDK 24.
82+
// Some JDK 21 builds (e.g. 21.0.10) backported Module.isNativeAccessEnabled(),
83+
// but it returns false even though JNI works fine without --enable-native-access.
84+
// See https://github.com/jline/jline3/issues/1689
85+
try {
86+
int version = Integer.parseInt(System.getProperty("java.specification.version"));
87+
if (version < 24) {
88+
return;
89+
}
90+
} catch (NumberFormatException e) {
91+
// JDK 8 uses "1.8" format, which means JDK < 24
92+
return;
93+
}
8194
try {
8295
Method getModule = Class.class.getMethod("getModule");
8396
Object module = getModule.invoke(JniTerminalProvider.class);
@@ -88,7 +101,7 @@ static void checkNativeAccess() {
88101
"Native access is not enabled for the current module: " + module);
89102
}
90103
} catch (NoSuchMethodException e) {
91-
// JDK < 9 (no modules) or JDK < 22 (no isNativeAccessEnabled), no restrictions
104+
// Method not available, no native access restrictions
92105
} catch (UnsupportedOperationException e) {
93106
throw e;
94107
} catch (ReflectiveOperationException e) {

terminal/src/main/java/org/jline/terminal/impl/exec/ExecTerminalProvider.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -693,13 +693,26 @@ public ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd) {
693693

694694
/**
695695
* Checks that native access is enabled for this module.
696-
* Uses reflection because {@code Module.isNativeAccessEnabled()} is only available on JDK 22+
697-
* and {@code Class.getModule()} is only available on JDK 9+.
698-
* On older JDKs, the check is skipped (no restrictions exist).
696+
* JNI native access restrictions are only enforced from JDK 24+, so the check
697+
* is skipped on earlier versions. Uses reflection because
698+
* {@code Module.isNativeAccessEnabled()} is not available on all JDK versions.
699699
*
700700
* @throws UnsupportedOperationException if native access is not enabled
701701
*/
702702
static void checkNativeAccess() {
703+
// JNI native access restrictions are only enforced starting from JDK 24.
704+
// Some JDK 21 builds (e.g. 21.0.10) backported Module.isNativeAccessEnabled(),
705+
// but it returns false even though JNI works fine without --enable-native-access.
706+
// See https://github.com/jline/jline3/issues/1689
707+
try {
708+
int version = Integer.parseInt(System.getProperty("java.specification.version"));
709+
if (version < 24) {
710+
return;
711+
}
712+
} catch (NumberFormatException e) {
713+
// JDK 8 uses "1.8" format, which means JDK < 24
714+
return;
715+
}
703716
try {
704717
Method getModule = Class.class.getMethod("getModule");
705718
Object module = getModule.invoke(ExecTerminalProvider.class);
@@ -710,7 +723,7 @@ static void checkNativeAccess() {
710723
"Native access is not enabled for the current module: " + module);
711724
}
712725
} catch (NoSuchMethodException e) {
713-
// JDK < 9 (no modules) or JDK < 22 (no isNativeAccessEnabled), no restrictions
726+
// Method not available, no native access restrictions
714727
} catch (UnsupportedOperationException e) {
715728
throw e;
716729
} catch (ReflectiveOperationException e) {

0 commit comments

Comments
 (0)