JDK-8057646 : ClassCircularityError running SQE test
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 9
  • Priority: P2
  • Status: Closed
  • Resolution: Not an Issue
  • Submitted: 2014-09-05
  • Updated: 2016-06-13
  • Resolved: 2015-07-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Resolved
Related Reports
Relates :  
Relates :  
Relates :  
Description
alanb: I've replaced the description with a full stack trace so that the issue is clearer:

Exception in thread "main" java.lang.ClassCircularityError: sun/util/cldr/CLDRLocaleDataMetaInfo
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:346)
	at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:370)
	at java.util.ServiceLoader$LazyIterator.access$700(ServiceLoader.java:323)
	at java.util.ServiceLoader$LazyIterator$2.run(ServiceLoader.java:407)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:409)
	at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
	at sun.util.locale.provider.JRELocaleProviderAdapter$1.run(JRELocaleProviderAdapter.java:382)
	at sun.util.locale.provider.JRELocaleProviderAdapter$1.run(JRELocaleProviderAdapter.java:377)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.util.locale.provider.JRELocaleProviderAdapter.createSupportedLocaleString(JRELocaleProviderAdapter.java:377)
	at sun.util.locale.provider.JRELocaleProviderAdapter.createLanguageTagSet(JRELocaleProviderAdapter.java:358)
	at sun.util.locale.provider.JRELocaleProviderAdapter.getLanguageTagSet(JRELocaleProviderAdapter.java:348)
	at sun.util.locale.provider.JRELocaleProviderAdapter.getNumberFormatProvider(JRELocaleProviderAdapter.java:206)
	at sun.util.locale.provider.JRELocaleProviderAdapter.getLocaleServiceProvider(JRELocaleProviderAdapter.java:97)
	at sun.util.locale.provider.LocaleProviderAdapter.findAdapter(LocaleProviderAdapter.java:284)
	at sun.util.locale.provider.LocaleProviderAdapter.getAdapter(LocaleProviderAdapter.java:254)
	at java.text.NumberFormat.getInstance(NumberFormat.java:859)
	at java.text.NumberFormat.getInstance(NumberFormat.java:442)
	at java.text.MessageFormat.subformat(MessageFormat.java:1271)
	at java.text.MessageFormat.format(MessageFormat.java:865)
	at java.text.Format.format(Format.java:157)
	at sun.security.provider.PolicyParser$ParsingException.<init>(PolicyParser.java:1409)
	at sun.security.provider.PolicyParser.parseGrantEntry(PolicyParser.java:546)
	at sun.security.provider.PolicyParser.read(PolicyParser.java:197)
	at sun.security.provider.PolicyFile.init(PolicyFile.java:605)
	at sun.security.provider.PolicyFile.access$400(PolicyFile.java:258)
	at sun.security.provider.PolicyFile$3.run(PolicyFile.java:521)
	at sun.security.provider.PolicyFile$3.run(PolicyFile.java:495)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.security.provider.PolicyFile.initPolicyFile(PolicyFile.java:495)
	at sun.security.provider.PolicyFile.initPolicyFile(PolicyFile.java:488)
	at sun.security.provider.PolicyFile.init(PolicyFile.java:439)
	at sun.security.provider.PolicyFile.<init>(PolicyFile.java:297)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:409)
	at java.lang.Class.newInstance(Class.java:439)
	at java.security.Policy.getPolicyNoCheck(Policy.java:184)
	at java.security.ProtectionDomain.implies(ProtectionDomain.java:272)
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:435)
	at java.security.AccessController.checkPermission(AccessController.java:894)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:541)
	at java.lang.SecurityManager.checkPackageAccess(SecurityManager.java:1479)
	at java.lang.ClassLoader$1.run(ClassLoader.java:504)
	at java.lang.ClassLoader$1.run(ClassLoader.java:502)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.lang.ClassLoader.checkPackageAccess(ClassLoader.java:502)
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:762)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:462)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:426)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:359)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:346)
	at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:370)
	at java.util.ServiceLoader$LazyIterator.access$700(ServiceLoader.java:323)
	at java.util.ServiceLoader$LazyIterator$2.run(ServiceLoader.java:407)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:409)
	at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
	at sun.util.locale.provider.JRELocaleProviderAdapter$1.run(JRELocaleProviderAdapter.java:382)
	at sun.util.locale.provider.JRELocaleProviderAdapter$1.run(JRELocaleProviderAdapter.java:377)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.util.locale.provider.JRELocaleProviderAdapter.createSupportedLocaleString(JRELocaleProviderAdapter.java:377)
	at sun.util.locale.provider.JRELocaleProviderAdapter.createLanguageTagSet(JRELocaleProviderAdapter.java:358)
	at sun.util.locale.provider.JRELocaleProviderAdapter.getLanguageTagSet(JRELocaleProviderAdapter.java:348)
	at sun.util.locale.provider.JRELocaleProviderAdapter.getNumberFormatProvider(JRELocaleProviderAdapter.java:206)
	at sun.util.locale.provider.JRELocaleProviderAdapter.getLocaleServiceProvider(JRELocaleProviderAdapter.java:97)
	at sun.util.locale.provider.LocaleProviderAdapter.findAdapter(LocaleProviderAdapter.java:284)
	at sun.util.locale.provider.LocaleProviderAdapter.getAdapter(LocaleProviderAdapter.java:254)
	at java.text.NumberFormat.getInstance(NumberFormat.java:859)
	at java.text.NumberFormat.getInstance(NumberFormat.java:442)
	at java.text.MessageFormat.subformat(MessageFormat.java:1271)
	at java.text.MessageFormat.format(MessageFormat.java:865)
	at java.text.Format.format(Format.java:157)
	at sun.security.provider.PolicyParser$ParsingException.<init>(PolicyParser.java:1409)
	at sun.security.provider.PolicyParser.parseGrantEntry(PolicyParser.java:546)
	at sun.security.provider.PolicyParser.read(PolicyParser.java:197)
	at sun.security.provider.PolicyFile.init(PolicyFile.java:605)
	at sun.security.provider.PolicyFile.access$400(PolicyFile.java:258)
	at sun.security.provider.PolicyFile$3.run(PolicyFile.java:521)
	at sun.security.provider.PolicyFile$3.run(PolicyFile.java:495)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.security.provider.PolicyFile.initPolicyFile(PolicyFile.java:495)
	at sun.security.provider.PolicyFile.initPolicyFile(PolicyFile.java:488)
	at sun.security.provider.PolicyFile.init(PolicyFile.java:439)
	at sun.security.provider.PolicyFile.<init>(PolicyFile.java:297)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:409)
	at java.lang.Class.newInstance(Class.java:439)
	at java.security.Policy.getPolicyNoCheck(Policy.java:184)
	at java.security.ProtectionDomain.implies(ProtectionDomain.java:272)
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:435)
	at java.security.AccessController.checkPermission(AccessController.java:894)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:541)
	at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1285)
	at java.lang.System.getProperty(System.java:713)
	at PBPolicy.main(PBPolicy.java:12)


Comments
Closed "Not an Issue" bugs without verification
13-06-2016

This is no longer an issue as something in the fix for JDK-8008577 has made the error go away. However, I did spend some time looking at this, and if it reappears again, I think I have an idea how to fix it. The problem occurs when the policy file is being initialized and something causes a permission check and there is a ProtectionDomain on the stack that has not been injected with the permissions from the policy file yet; for example in this case this ProtectionDomain was on the stack: domain 0 ProtectionDomain (jrt:/jdk.localedata <no signer certificates>) sun.misc.Launcher$ExtClassLoader@75bd9247 <no principals> java.security.Permissions@7dc36524 ( ("java.io.FilePermission" "/home/.../hg/jdk9/jep232/8072692/build/linux-x86_64-normal-server-fastdebug/images/jdk/-" "read") ) but did not yet have the additional permissions granted to it in the JRE java.policy file: grant codeBase "jrt:/jdk.localedata" { permission java.lang.RuntimePermission "accessClassInPackage.sun.text.*"; permission java.lang.RuntimePermission "accessClassInPackage.sun.util.*"; permission java.util.PropertyPermission "*", "read"; }; The problem is that the permission checking code tries to parse all the configured policy files before granting the permissions, and thus recursively hits the same error (the syntax error in the test's policy file). We could change the code to be proactive, and as soon as it finds a permission that implies the required permission, it returns. I think this would stop the recursion. Since permission granting is a union (not an intersection) of all the policy grant entries, I think this might work.
09-07-2015

I think the fix for JDK-8008577 is affecting the test failures seen in this bug. Impacted tests no longer fail with ClassCircularityError.
26-06-2015

When PolicyParser fails to parse the input policy file due to e.g. syntax error, the current implementation will format the exception message for localization. This initialization code is fragile and prone to recursion when methods requiring permission check is called during the initialization of PolicyFile. This code needs re-examination together with JDK-8075706.
30-03-2015

Exception in thread "main" java.lang.ClassCircularityError: sun/util/resources/provider/NonEnLocaleDataMetaInfo at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:370) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:368) at java.util.ServiceLoader$LazyIterator.access$700(ServiceLoader.java:321) at java.util.ServiceLoader$LazyIterator$2.run(ServiceLoader.java:405) at java.security.AccessController.doPrivileged(Native Method) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:407) at java.util.ServiceLoader$1.next(ServiceLoader.java:478) at sun.util.locale.provider.JRELocaleProviderAdapter$1.run(JRELocaleProviderAdapter.java:382) at sun.util.locale.provider.JRELocaleProviderAdapter$1.run(JRELocaleProviderAdapter.java:377) at java.security.AccessController.doPrivileged(Native Method) at sun.util.locale.provider.JRELocaleProviderAdapter.createSupportedLocaleString(JRELocaleProviderAdapter.java:377) at sun.util.locale.provider.JRELocaleProviderAdapter.createLanguageTagSet(JRELocaleProviderAdapter.java:358) at sun.util.locale.provider.JRELocaleProviderAdapter.getLanguageTagSet(JRELocaleProviderAdapter.java:348) at sun.util.locale.provider.JRELocaleProviderAdapter.getNumberFormatProvider(JRELocaleProviderAdapter.java:206) at sun.util.locale.provider.JRELocaleProviderAdapter.getLocaleServiceProvider(JRELocaleProviderAdapter.java:97) at sun.util.locale.provider.LocaleProviderAdapter.findAdapter(LocaleProviderAdapter.java:284) at sun.util.locale.provider.LocaleProviderAdapter.getAdapter(LocaleProviderAdapter.java:254) at java.text.NumberFormat.getInstance(NumberFormat.java:859) at java.text.NumberFormat.getInstance(NumberFormat.java:442) at java.text.MessageFormat.subformat(MessageFormat.java:1271) at java.text.MessageFormat.format(MessageFormat.java:865) at java.text.Format.format(Format.java:157) . . . . .
19-02-2015

Transferred this issue to the security-libs, where the problem can be addressed on the spot. Here is the link to my attempt to fix it in i18n, in which the test case can be reused for security engineers. http://cr.openjdk.java.net/~naoto/8057646/webrev.0/
09-09-2014

The changes in JDK-8038436 have clearly tickled this issue but I think they have just exposed an area of the PolicyFile code that is very fragile. The right solution might be to audit the PolicyFile and PolicyParser code for places where they execute code that could trigger another permission check and a recursive attempt to load the policy file. If we don't do this then it will bite us again, maybe when ResourceBundle is updated to make use of ServiceLoader.
09-09-2014

There is already code in java.security.Policy which switches to using the default JDK policy provider when bootstrapping if there are issues loading a custom policy provider. However, that code is only triggered if there is an exception thrown (and not an Error) when loading the custom policy provider, hence the fallback was not tried in this case. Anyway, I don't think the current Policy fallback/bootstrap code is ideal and there may be a better way to handle cases like this, so I agree with Alan that this is worth reviewing.
09-09-2014

The root cause of the problem was that with an erroneous policy file, PolicyParser tries to use java.text.NumberFormat instance on reading it for throwing ParsingException. Then inside NumberFormat.getInstance() it again calls ServiceLoader.loadInstalled() for loading non-EN locale data, w induces checkPermission() call resulting in this circular error. To avoid this, this circularity error must also be caught and ignored gracefully.
08-09-2014

Caused by the fix to 8038436. Will need to take care of this circularity error as well as other possible exceptions during LocaleDataMetaInfo provider look-up.
05-09-2014

Reassigning to core-libs for further evaluation since it looks like JDK-8038436 triggered this regression.
05-09-2014

RULE JAAS/policy/PBnoBracesSyntaxPolicy Exception java.lang.ClassCircularityError: sun/util/resources/provider/NonEnLocaleDataMetaInfo RULE JAAS/policy/PBnoColenSyntaxPolicy Exception java.lang.ClassCircularityError: sun/util/resources/provider/NonEnLocaleDataMetaInfo RULE JAAS/policy/PBnoBracesSyntaxPolicy Exception java.lang.ClassCircularityError: sun/util/cldr/CLDRLocaleDataMetaInfo RULE JAAS/policy/PBnoColenSyntaxPolicy Exception java.lang.ClassCircularityError: sun/util/cldr/CLDRLocaleDataMetaInfo
05-09-2014