Issue
I'm upgrading jdk 8 to 11.
I load some class in checkPermission
method then security manager emit recursive update
exception. but use jdk1.8.0_202
everything works fine.
What causes this problem?
OS: macOS 10.15.6
JDK(Oracle): 11.0.8
IDE: Intellij 2019 3
- Main
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
- SecurityManager
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);
}
}
Run with
-Djava.security.manager=sm.MySecurityManager
Console logs
Error occurred during initialization of VM
java.lang.BootstrapMethodError: bootstrap method initialization exception
at java.lang.invoke.BootstrapMethodInvoker.invoke([email protected]/BootstrapMethodInvoker.java:194)
at java.lang.invoke.CallSite.makeSite([email protected]/CallSite.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl([email protected]/MethodHandleNatives.java:258)
at java.lang.invoke.MethodHandleNatives.linkCallSite([email protected]/MethodHandleNatives.java:248)
at sun.net.www.protocol.jrt.JavaRuntimeURLConnection.<clinit>([email protected]/JavaRuntimeURLConnection.java:55)
at sun.net.www.protocol.jrt.Handler.openConnection([email protected]/Handler.java:42)
at java.net.URL.openConnection([email protected]/URL.java:1074)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.checkPermissionToConnect([email protected]/SystemModuleFinders.java:405)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.<init>([email protected]/SystemModuleFinders.java:414)
at jdk.internal.module.SystemModuleFinders$2.get([email protected]/SystemModuleFinders.java:315)
at jdk.internal.module.SystemModuleFinders$2.get([email protected]/SystemModuleFinders.java:312)
at jdk.internal.module.ModuleReferenceImpl.open([email protected]/ModuleReferenceImpl.java:93)
at jdk.internal.loader.BuiltinClassLoader$5.apply([email protected]/BuiltinClassLoader.java:961)
at jdk.internal.loader.BuiltinClassLoader$5.apply([email protected]/BuiltinClassLoader.java:958)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent([email protected]/ConcurrentHashMap.java:1705)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor([email protected]/BuiltinClassLoader.java:969)
at jdk.internal.loader.BuiltinClassLoader.defineClass([email protected]/BuiltinClassLoader.java:731)
at jdk.internal.loader.BuiltinClassLoader.lambda$findClassInModuleOrNull$2([email protected]/BuiltinClassLoader.java:682)
at java.security.AccessController.doPrivileged([email protected]/Native Method)
at jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull([email protected]/BuiltinClassLoader.java:683)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull([email protected]/BuiltinClassLoader.java:605)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull([email protected]/BuiltinClassLoader.java:640)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull([email protected]/BuiltinClassLoader.java:609)
at jdk.internal.loader.BuiltinClassLoader.loadClass([email protected]/BuiltinClassLoader.java:579)
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass([email protected]/ClassLoaders.java:178)
at java.lang.ClassLoader.loadClass([email protected]/ClassLoader.java:521)
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
at java.lang.SecurityManager.checkPropertyAccess([email protected]/SecurityManager.java:1066)
at java.lang.System.getProperty([email protected]/System.java:814)
at java.lang.ClassLoader.initSystemClassLoader([email protected]/ClassLoader.java:1971)
at java.lang.System.initPhase3([email protected]/System.java:2070)
Caused by: java.lang.IllegalStateException: Recursive update
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent([email protected]/ConcurrentHashMap.java:1760)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor([email protected]/BuiltinClassLoader.java:969)
at jdk.internal.loader.BuiltinClassLoader.defineClass([email protected]/BuiltinClassLoader.java:731)
at jdk.internal.loader.BuiltinClassLoader.lambda$findClassInModuleOrNull$2([email protected]/BuiltinClassLoader.java:682)
at java.security.AccessController.doPrivileged([email protected]/Native Method)
at jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull([email protected]/BuiltinClassLoader.java:683)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull([email protected]/BuiltinClassLoader.java:605)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull([email protected]/BuiltinClassLoader.java:640)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull([email protected]/BuiltinClassLoader.java:609)
at jdk.internal.loader.BuiltinClassLoader.loadClass([email protected]/BuiltinClassLoader.java:579)
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass([email protected]/ClassLoaders.java:178)
at java.lang.ClassLoader.loadClass([email protected]/ClassLoader.java:521)
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
at java.lang.reflect.AccessibleObject.checkPermission([email protected]/AccessibleObject.java:83)
at java.lang.reflect.Constructor.setAccessible([email protected]/Constructor.java:180)
at java.lang.invoke.InnerClassLambdaMetafactory$1.run([email protected]/InnerClassLambdaMetafactory.java:206)
at java.lang.invoke.InnerClassLambdaMetafactory$1.run([email protected]/InnerClassLambdaMetafactory.java:199)
at java.security.AccessController.doPrivileged([email protected]/Native Method)
at java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite([email protected]/InnerClassLambdaMetafactory.java:198)
at java.lang.invoke.LambdaMetafactory.metafactory([email protected]/LambdaMetafactory.java:329)
at java.lang.invoke.BootstrapMethodInvoker.invoke([email protected]/BootstrapMethodInvoker.java:127)
at java.lang.invoke.CallSite.makeSite([email protected]/CallSite.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl([email protected]/MethodHandleNatives.java:258)
at java.lang.invoke.MethodHandleNatives.linkCallSite([email protected]/MethodHandleNatives.java:248)
at sun.net.www.protocol.jrt.JavaRuntimeURLConnection.<clinit>([email protected]/JavaRuntimeURLConnection.java:55)
at sun.net.www.protocol.jrt.Handler.openConnection([email protected]/Handler.java:42)
at java.net.URL.openConnection([email protected]/URL.java:1074)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.checkPermissionToConnect([email protected]/SystemModuleFinders.java:405)
at jdk.internal.module.SystemModuleFinders$SystemModuleReader.<init>([email protected]/SystemModuleFinders.java:414)
at jdk.internal.module.SystemModuleFinders$2.get([email protected]/SystemModuleFinders.java:315)
at jdk.internal.module.SystemModuleFinders$2.get([email protected]/SystemModuleFinders.java:312)
at jdk.internal.module.ModuleReferenceImpl.open([email protected]/ModuleReferenceImpl.java:93)
at jdk.internal.loader.BuiltinClassLoader$5.apply([email protected]/BuiltinClassLoader.java:961)
at jdk.internal.loader.BuiltinClassLoader$5.apply([email protected]/BuiltinClassLoader.java:958)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent([email protected]/ConcurrentHashMap.java:1705)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor([email protected]/BuiltinClassLoader.java:969)
at jdk.internal.loader.BuiltinClassLoader.defineClass([email protected]/BuiltinClassLoader.java:731)
at jdk.internal.loader.BuiltinClassLoader.lambda$findClassInModuleOrNull$2([email protected]/BuiltinClassLoader.java:682)
at java.security.AccessController.doPrivileged([email protected]/Native Method)
at jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull([email protected]/BuiltinClassLoader.java:683)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull([email protected]/BuiltinClassLoader.java:605)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull([email protected]/BuiltinClassLoader.java:640)
at jdk.internal.loader.BuiltinClassLoader.loadClassOrNull([email protected]/BuiltinClassLoader.java:609)
at jdk.internal.loader.BuiltinClassLoader.loadClass([email protected]/BuiltinClassLoader.java:579)
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass([email protected]/ClassLoaders.java:178)
at java.lang.ClassLoader.loadClass([email protected]/ClassLoader.java:521)
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
at java.lang.SecurityManager.checkPropertyAccess([email protected]/SecurityManager.java:1066)
at java.lang.System.getProperty([email protected]/System.java:814)
at java.lang.ClassLoader.initSystemClassLoader([email protected]/ClassLoader.java:1971)
at java.lang.System.initPhase3([email protected]/System.java:2070)
Process finished with exit code 1
Solution
The stack trace indicates that the issue is connected with the module loading rather than class loading, which explains why you don’t have the problem in JDK 8 that doesn’t have modules.
When you read the stack trace starting at the bottom, i.e.
at java.lang.System.initPhase3([email protected]/System.java:2070)
you will encounter the stack frames
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent([email protected]/ConcurrentHashMap.java:1705)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor([email protected]/BuiltinClassLoader.java:969)
indicating an attempt to load a module. This will eventually end up at a privileged action that needs a check, so you’ll find the line
at sm.MySecurityManager.checkPermission(MySecurityManager.java:11)
which triggers the loading of javax.security.auth.kerberos.ServicePermission
which is in the module java.security.jgss
which apparently has not been loaded before.
So the loadClass
call ends up again at
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent([email protected]/ConcurrentHashMap.java:1760)
at jdk.internal.loader.BuiltinClassLoader.moduleReaderFor([email protected]/BuiltinClassLoader.java:969)
which triggers the “java.lang.IllegalStateException: Recursive update”, as calling computeIfAbsent
is not allowed from another computeIfAbsent
call on the same ConcurrentHashMap
. Since ignoring this constraint can lead to corrupted maps, a check has been added in Java 9 to reject such attempts. See this Q&A.
Generally, triggering class loading from a security manager that might get checked again during the class loading can be problematic. I suggest resorting to the documented toString()
output for comparison. After all, that’s what the policy file based security implementation does as well.
Since ServicePermission
is final
, a cheaper permission.getClass().getName().equals( "javax.security.auth.kerberos.ServicePermission")
would do as well. Both approaches avoid loading the permission if it has not been used before. As indicated by the issue, this may even save the loading of an entire module.
Answered By - Holger
Answer Checked By - Senaida (JavaFixing Volunteer)