在 checkPermission 方法中加载一些 class 时,为什么 SecurityManager 会发出递归更新异常?
When load some class in checkPermission method why SecurityManager emit recursive update exception?
我正在将 jdk 8 升级到 11。
我在 checkPermission
方法中加载了一些 class,然后安全管理器发出 recursive update
异常。但使用 jdk1.8.0_202
一切正常。
导致此问题的原因是什么?
- 我的环境。
OS: macOS 10.15.6
JDK(Oracle): 11.0.8
IDE: Intellij 2019 3
- 主要
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
- 安全管理器
package sm;
import java.security.Permission;
public class MySecurityManager extends SecurityManager {
@Override
public void checkPermission(Permission permission) {
// Problem occurs when load ServicePermission.class
if (permission instanceof javax.security.auth.kerberos.ServicePermission) {
// throw new SecurityException("javax.security.auth.kerberos.ServicePermission is not allowed.");
}
}
@Override
public void checkPermission(Permission permission, Object context) {
this.checkPermission(permission);
}
}
运行 与 -Djava.security.manager=sm.MySecurityManager
控制台日志
Error occurred during initialization of VM
java.lang.BootstrapMethodError: bootstrap method initialization exception
at java.lang.invoke.BootstrapMethodInvoker.invoke(java.base@11.0.8/BootstrapMethodInvoker.java:194)
at java.lang.invoke.CallSite.makeSite(java.base@11.0.8/CallSite.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(java.base@11.0.8/MethodHandleNatives.java:258)
at java.lang.invoke.MethodHandleNatives.linkCallSite(java.base@11.0.8/MethodHandleNatives.java:248)
at sun.net.www.protocol.jrt.JavaRuntimeURLConnection.<clinit>(java.base@11.0.8/JavaRuntimeURLConnection.java:55)
at sun.net.www.protocol.jrt.Handler.openConnection(java.base@11.0.8/Handler.java:42)
at java.net.URL.openConnection(java.base@11.0.8/URL.java:1074)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.checkPermissionToConnect(java.base@11.0.8/SystemModuleFinders.java:405)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.<init>(java.base@11.0.8/SystemModuleFinders.java:414)
at jdk.internal.module.SystemModuleFinders.get(java.base@11.0.8/SystemModuleFinders.java:315)
at jdk.internal.module.SystemModuleFinders.get(java.base@11.0.8/SystemModuleFinders.java:312)
at jdk.internal.module.ModuleReferenceImpl.open(java.base@11.0.8/ModuleReferenceImpl.java:93)
at jdk.internal.loader.BuiltinClassLoader.apply(java.base@11.0.8/BuiltinClassLoader.java:961)
at jdk.internal.loader.BuiltinClassLoader.apply(java.base@11.0.8/BuiltinClassLoader.java:958)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1705)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
at jdk.internal.loader.BuiltinClassLoader.defineClass(java.base@11.0.8/BuiltinClassLoader.java:731)
at jdk.internal.loader.BuiltinClassLoader.lambda$findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:682)
at java.security.AccessController.doPrivileged(java.base@11.0.8/Native Method)
at jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:683)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:605)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:640)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:609)
at jdk.internal.loader.BuiltinClassLoader.loadClass(java.base@11.0.8/BuiltinClassLoader.java:579)
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(java.base@11.0.8/ClassLoaders.java:178)
at java.lang.ClassLoader.loadClass(java.base@11.0.8/ClassLoader.java:521)
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
at java.lang.SecurityManager.checkPropertyAccess(java.base@11.0.8/SecurityManager.java:1066)
at java.lang.System.getProperty(java.base@11.0.8/System.java:814)
at java.lang.ClassLoader.initSystemClassLoader(java.base@11.0.8/ClassLoader.java:1971)
at java.lang.System.initPhase3(java.base@11.0.8/System.java:2070)
Caused by: java.lang.IllegalStateException: Recursive update
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1760)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
at jdk.internal.loader.BuiltinClassLoader.defineClass(java.base@11.0.8/BuiltinClassLoader.java:731)
at jdk.internal.loader.BuiltinClassLoader.lambda$findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:682)
at java.security.AccessController.doPrivileged(java.base@11.0.8/Native Method)
at jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:683)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:605)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:640)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:609)
at jdk.internal.loader.BuiltinClassLoader.loadClass(java.base@11.0.8/BuiltinClassLoader.java:579)
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(java.base@11.0.8/ClassLoaders.java:178)
at java.lang.ClassLoader.loadClass(java.base@11.0.8/ClassLoader.java:521)
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
at java.lang.reflect.AccessibleObject.checkPermission(java.base@11.0.8/AccessibleObject.java:83)
at java.lang.reflect.Constructor.setAccessible(java.base@11.0.8/Constructor.java:180)
at java.lang.invoke.InnerClassLambdaMetafactory.run(java.base@11.0.8/InnerClassLambdaMetafactory.java:206)
at java.lang.invoke.InnerClassLambdaMetafactory.run(java.base@11.0.8/InnerClassLambdaMetafactory.java:199)
at java.security.AccessController.doPrivileged(java.base@11.0.8/Native Method)
at java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(java.base@11.0.8/InnerClassLambdaMetafactory.java:198)
at java.lang.invoke.LambdaMetafactory.metafactory(java.base@11.0.8/LambdaMetafactory.java:329)
at java.lang.invoke.BootstrapMethodInvoker.invoke(java.base@11.0.8/BootstrapMethodInvoker.java:127)
at java.lang.invoke.CallSite.makeSite(java.base@11.0.8/CallSite.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(java.base@11.0.8/MethodHandleNatives.java:258)
at java.lang.invoke.MethodHandleNatives.linkCallSite(java.base@11.0.8/MethodHandleNatives.java:248)
at sun.net.www.protocol.jrt.JavaRuntimeURLConnection.<clinit>(java.base@11.0.8/JavaRuntimeURLConnection.java:55)
at sun.net.www.protocol.jrt.Handler.openConnection(java.base@11.0.8/Handler.java:42)
at java.net.URL.openConnection(java.base@11.0.8/URL.java:1074)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.checkPermissionToConnect(java.base@11.0.8/SystemModuleFinders.java:405)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.<init>(java.base@11.0.8/SystemModuleFinders.java:414)
at jdk.internal.module.SystemModuleFinders.get(java.base@11.0.8/SystemModuleFinders.java:315)
at jdk.internal.module.SystemModuleFinders.get(java.base@11.0.8/SystemModuleFinders.java:312)
at jdk.internal.module.ModuleReferenceImpl.open(java.base@11.0.8/ModuleReferenceImpl.java:93)
at jdk.internal.loader.BuiltinClassLoader.apply(java.base@11.0.8/BuiltinClassLoader.java:961)
at jdk.internal.loader.BuiltinClassLoader.apply(java.base@11.0.8/BuiltinClassLoader.java:958)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1705)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
at jdk.internal.loader.BuiltinClassLoader.defineClass(java.base@11.0.8/BuiltinClassLoader.java:731)
at jdk.internal.loader.BuiltinClassLoader.lambda$findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:682)
at java.security.AccessController.doPrivileged(java.base@11.0.8/Native Method)
at jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:683)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:605)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:640)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:609)
at jdk.internal.loader.BuiltinClassLoader.loadClass(java.base@11.0.8/BuiltinClassLoader.java:579)
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(java.base@11.0.8/ClassLoaders.java:178)
at java.lang.ClassLoader.loadClass(java.base@11.0.8/ClassLoader.java:521)
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
at java.lang.SecurityManager.checkPropertyAccess(java.base@11.0.8/SecurityManager.java:1066)
at java.lang.System.getProperty(java.base@11.0.8/System.java:814)
at java.lang.ClassLoader.initSystemClassLoader(java.base@11.0.8/ClassLoader.java:1971)
at java.lang.System.initPhase3(java.base@11.0.8/System.java:2070)
Process finished with exit code 1
堆栈跟踪表明问题与 模块加载 而不是 class 加载有关,这解释了为什么 [=] 中没有问题53=] 8 没有模块。
当您从底部开始读取堆栈跟踪时,即
at java.lang.System.initPhase3(java.base@11.0.8/System.java:2070)
你会遇到栈帧
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1705)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
表示试图加载模块。这最终将以需要检查的特权操作结束,因此您会找到行
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
这会触发模块 java.security.jgss
中的 javax.security.auth.kerberos.ServicePermission
的加载,显然以前没有加载过。
因此 loadClass
通话再次结束于
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1760)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
这会触发“java.lang.IllegalStateException:递归更新”,因为不允许从另一个 computeIfAbsent
对同一 ConcurrentHashMap
的调用调用 computeIfAbsent
。由于忽略此约束会导致地图损坏,因此在 Java 9 中添加了一项检查以拒绝此类尝试。参见 。
通常,从可能在 class 加载期间再次检查的安全管理器触发 class 加载可能会出现问题。我建议求助于 documented toString()
output 进行比较。毕竟,这也是基于策略文件的安全实现所做的。
因为 ServicePermission
是 final
,所以更便宜的 permission.getClass().getName().equals( "javax.security.auth.kerberos.ServicePermission")
也可以。如果以前没有使用过,这两种方法都会避免加载权限。如问题所示,这甚至可以节省整个模块的加载。
我正在将 jdk 8 升级到 11。
我在 checkPermission
方法中加载了一些 class,然后安全管理器发出 recursive update
异常。但使用 jdk1.8.0_202
一切正常。
导致此问题的原因是什么?
- 我的环境。
OS: macOS 10.15.6
JDK(Oracle): 11.0.8
IDE: Intellij 2019 3
- 主要
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
- 安全管理器
package sm;
import java.security.Permission;
public class MySecurityManager extends SecurityManager {
@Override
public void checkPermission(Permission permission) {
// Problem occurs when load ServicePermission.class
if (permission instanceof javax.security.auth.kerberos.ServicePermission) {
// throw new SecurityException("javax.security.auth.kerberos.ServicePermission is not allowed.");
}
}
@Override
public void checkPermission(Permission permission, Object context) {
this.checkPermission(permission);
}
}
运行 与
-Djava.security.manager=sm.MySecurityManager
控制台日志
Error occurred during initialization of VM
java.lang.BootstrapMethodError: bootstrap method initialization exception
at java.lang.invoke.BootstrapMethodInvoker.invoke(java.base@11.0.8/BootstrapMethodInvoker.java:194)
at java.lang.invoke.CallSite.makeSite(java.base@11.0.8/CallSite.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(java.base@11.0.8/MethodHandleNatives.java:258)
at java.lang.invoke.MethodHandleNatives.linkCallSite(java.base@11.0.8/MethodHandleNatives.java:248)
at sun.net.www.protocol.jrt.JavaRuntimeURLConnection.<clinit>(java.base@11.0.8/JavaRuntimeURLConnection.java:55)
at sun.net.www.protocol.jrt.Handler.openConnection(java.base@11.0.8/Handler.java:42)
at java.net.URL.openConnection(java.base@11.0.8/URL.java:1074)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.checkPermissionToConnect(java.base@11.0.8/SystemModuleFinders.java:405)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.<init>(java.base@11.0.8/SystemModuleFinders.java:414)
at jdk.internal.module.SystemModuleFinders.get(java.base@11.0.8/SystemModuleFinders.java:315)
at jdk.internal.module.SystemModuleFinders.get(java.base@11.0.8/SystemModuleFinders.java:312)
at jdk.internal.module.ModuleReferenceImpl.open(java.base@11.0.8/ModuleReferenceImpl.java:93)
at jdk.internal.loader.BuiltinClassLoader.apply(java.base@11.0.8/BuiltinClassLoader.java:961)
at jdk.internal.loader.BuiltinClassLoader.apply(java.base@11.0.8/BuiltinClassLoader.java:958)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1705)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
at jdk.internal.loader.BuiltinClassLoader.defineClass(java.base@11.0.8/BuiltinClassLoader.java:731)
at jdk.internal.loader.BuiltinClassLoader.lambda$findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:682)
at java.security.AccessController.doPrivileged(java.base@11.0.8/Native Method)
at jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:683)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:605)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:640)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:609)
at jdk.internal.loader.BuiltinClassLoader.loadClass(java.base@11.0.8/BuiltinClassLoader.java:579)
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(java.base@11.0.8/ClassLoaders.java:178)
at java.lang.ClassLoader.loadClass(java.base@11.0.8/ClassLoader.java:521)
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
at java.lang.SecurityManager.checkPropertyAccess(java.base@11.0.8/SecurityManager.java:1066)
at java.lang.System.getProperty(java.base@11.0.8/System.java:814)
at java.lang.ClassLoader.initSystemClassLoader(java.base@11.0.8/ClassLoader.java:1971)
at java.lang.System.initPhase3(java.base@11.0.8/System.java:2070)
Caused by: java.lang.IllegalStateException: Recursive update
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1760)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
at jdk.internal.loader.BuiltinClassLoader.defineClass(java.base@11.0.8/BuiltinClassLoader.java:731)
at jdk.internal.loader.BuiltinClassLoader.lambda$findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:682)
at java.security.AccessController.doPrivileged(java.base@11.0.8/Native Method)
at jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:683)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:605)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:640)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:609)
at jdk.internal.loader.BuiltinClassLoader.loadClass(java.base@11.0.8/BuiltinClassLoader.java:579)
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(java.base@11.0.8/ClassLoaders.java:178)
at java.lang.ClassLoader.loadClass(java.base@11.0.8/ClassLoader.java:521)
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
at java.lang.reflect.AccessibleObject.checkPermission(java.base@11.0.8/AccessibleObject.java:83)
at java.lang.reflect.Constructor.setAccessible(java.base@11.0.8/Constructor.java:180)
at java.lang.invoke.InnerClassLambdaMetafactory.run(java.base@11.0.8/InnerClassLambdaMetafactory.java:206)
at java.lang.invoke.InnerClassLambdaMetafactory.run(java.base@11.0.8/InnerClassLambdaMetafactory.java:199)
at java.security.AccessController.doPrivileged(java.base@11.0.8/Native Method)
at java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(java.base@11.0.8/InnerClassLambdaMetafactory.java:198)
at java.lang.invoke.LambdaMetafactory.metafactory(java.base@11.0.8/LambdaMetafactory.java:329)
at java.lang.invoke.BootstrapMethodInvoker.invoke(java.base@11.0.8/BootstrapMethodInvoker.java:127)
at java.lang.invoke.CallSite.makeSite(java.base@11.0.8/CallSite.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(java.base@11.0.8/MethodHandleNatives.java:258)
at java.lang.invoke.MethodHandleNatives.linkCallSite(java.base@11.0.8/MethodHandleNatives.java:248)
at sun.net.www.protocol.jrt.JavaRuntimeURLConnection.<clinit>(java.base@11.0.8/JavaRuntimeURLConnection.java:55)
at sun.net.www.protocol.jrt.Handler.openConnection(java.base@11.0.8/Handler.java:42)
at java.net.URL.openConnection(java.base@11.0.8/URL.java:1074)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.checkPermissionToConnect(java.base@11.0.8/SystemModuleFinders.java:405)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.<init>(java.base@11.0.8/SystemModuleFinders.java:414)
at jdk.internal.module.SystemModuleFinders.get(java.base@11.0.8/SystemModuleFinders.java:315)
at jdk.internal.module.SystemModuleFinders.get(java.base@11.0.8/SystemModuleFinders.java:312)
at jdk.internal.module.ModuleReferenceImpl.open(java.base@11.0.8/ModuleReferenceImpl.java:93)
at jdk.internal.loader.BuiltinClassLoader.apply(java.base@11.0.8/BuiltinClassLoader.java:961)
at jdk.internal.loader.BuiltinClassLoader.apply(java.base@11.0.8/BuiltinClassLoader.java:958)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1705)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
at jdk.internal.loader.BuiltinClassLoader.defineClass(java.base@11.0.8/BuiltinClassLoader.java:731)
at jdk.internal.loader.BuiltinClassLoader.lambda$findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:682)
at java.security.AccessController.doPrivileged(java.base@11.0.8/Native Method)
at jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(java.base@11.0.8/BuiltinClassLoader.java:683)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:605)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:640)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(java.base@11.0.8/BuiltinClassLoader.java:609)
at jdk.internal.loader.BuiltinClassLoader.loadClass(java.base@11.0.8/BuiltinClassLoader.java:579)
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(java.base@11.0.8/ClassLoaders.java:178)
at java.lang.ClassLoader.loadClass(java.base@11.0.8/ClassLoader.java:521)
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
at java.lang.SecurityManager.checkPropertyAccess(java.base@11.0.8/SecurityManager.java:1066)
at java.lang.System.getProperty(java.base@11.0.8/System.java:814)
at java.lang.ClassLoader.initSystemClassLoader(java.base@11.0.8/ClassLoader.java:1971)
at java.lang.System.initPhase3(java.base@11.0.8/System.java:2070)
Process finished with exit code 1
堆栈跟踪表明问题与 模块加载 而不是 class 加载有关,这解释了为什么 [=] 中没有问题53=] 8 没有模块。
当您从底部开始读取堆栈跟踪时,即
at java.lang.System.initPhase3(java.base@11.0.8/System.java:2070)
你会遇到栈帧
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1705)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
表示试图加载模块。这最终将以需要检查的特权操作结束,因此您会找到行
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
这会触发模块 java.security.jgss
中的 javax.security.auth.kerberos.ServicePermission
的加载,显然以前没有加载过。
因此 loadClass
通话再次结束于
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(java.base@11.0.8/ConcurrentHashMap.java:1760)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(java.base@11.0.8/BuiltinClassLoader.java:969)
这会触发“java.lang.IllegalStateException:递归更新”,因为不允许从另一个 computeIfAbsent
对同一 ConcurrentHashMap
的调用调用 computeIfAbsent
。由于忽略此约束会导致地图损坏,因此在 Java 9 中添加了一项检查以拒绝此类尝试。参见
通常,从可能在 class 加载期间再次检查的安全管理器触发 class 加载可能会出现问题。我建议求助于 documented toString()
output 进行比较。毕竟,这也是基于策略文件的安全实现所做的。
因为 ServicePermission
是 final
,所以更便宜的 permission.getClass().getName().equals( "javax.security.auth.kerberos.ServicePermission")
也可以。如果以前没有使用过,这两种方法都会避免加载权限。如问题所示,这甚至可以节省整个模块的加载。