JDK-8199940 : Print more information about class loaders in IllegalAccessErrors
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 11
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2018-03-21
  • Updated: 2018-07-06
  • Resolved: 2018-06-27
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 11 JDK 12
11 b20Fixed 12Fixed
Related Reports
Relates :  
Relates :  
Description
Print more information about class loaders in IllegalAccessErrors
 
Since Java 9, class loaders have a name field. Report this if set.
Also report the parent class loader.
It was decided to not report the parent class loader, but to add the module.
The exceptions now use a unified reporting utility for the module/loader information.

Changed messages:

before:
class test.IAE1_B cannot access its superinterface test.IAE1_A

after:
class test.IAE1_B cannot access its superinterface test.IAE1_A (test.IAE1_B is in unnamed module of loader test.IAE_Loader1 @<id>; test.IAE1_A is in unnamed module of loader 'app')
or
class test.IAE1_B cannot access its superinterface test.IAE1_A (test.IAE1_B is in unnamed module of loader 'someCLName1' @<id>; test.IAE1_A is in unnamed module of loader 'app')

before:
class test.IAE2_B cannot access its superclass test.IAE2_A
or
class test.IAE3_B cannot access its superclass test.IAE3_A

after:
class test.IAE2_B cannot access its abstract superclass test.IAE2_A (test.IAE2_B is in unnamed module of loader 
'someCLName2' @<id>; test.IAE2_A is in unnamed module of loader 'app')
or 
class test.IAE3_B cannot access its superclass test.IAE3_A (test.IAE3_B is in unnamed module of loader 'someCLName3' @<id>; test.IAE3_A is in unnamed module of loader 'app')

before:
tried to access method test.IllegalAccessErrorTest.iae4_m()V from class test.Runner4

after: 
class test.Runner4 tried to access private method test.IllegalAccessErrorTest.iae4_m()V (test.Runner4 and test.IllegalAccessErrorTest are in unnamed module of loader 'app')

before:
tried to access field test.IllegalAccessErrorTest.iae5_f from class test.Runner5 

after:
class test.Runner5 tried to access private field test.IllegalAccessErrorTest.iae5_f (test.Runner5 and test.IllegalAccessErrorTest are in unnamed module of loader 'app')

before:
failed to access class test.IAE6_A from class test.IAE6_B

after:
failed to access class test.IAE6_A from class test.IAE6_B (test.IAE6_A is in unnamed module of loader 'app'; test.IAE6_B is in unnamed module of loader 'test6_class_CL' @<id>
Comments
> Goetz, had a long talk with Lois and studied your latest changes. > 1. Really appreciate that you are working with us to improve the error messages to be more helpful and specifically adding information such as class loader names. Thanks! > 2. Adding the class loader delegation parent is not appropriate for the direction we are going. Specifically as we move to modules, the class loaders may perform direct delegation for classes in packages in named modules in their Layer, only delegating to the class loader delegation parent for classes in packages in the unnamed module. Unfortunately the adoption of Java 9+ is still very low in SAP. Also, we have a lot of legacy software that hopefully will move to Java 11 at some point. This software will not be rewritten for modules, thus all the old problems will remain. Therefore handling these problems is my focus. We don't have experience with supporting software with modules yet. > Even today, without modules, we have customers with many class loaders, not all of which follow the delegation parent model. Yes, we too. We added a field 'String[] parents' to the classloader. Custom implemented class loaders list in this array all loaders to which they might delegate. One of them may be the loader from the parent field. Also, we added a field 'String [] URLs' which lists the URLs or classpath used by the loader. Similarly, this must be filled by the application in most cases. This is very useful! We added a unique ID to the classloader for cases where the name is not set (our class loaders have names since Java 4). All these fields are just for informational purposes. All this informationn is printed in the exceptions I modified. But it is also consumed by our tools. We might get involved in improving flight recorder and, once it is open sourced, mission control, and then will come back to this, again. > So this information could be misleading since it might not be pertinent to the mapping from initiating class loader to defining class loader. I don't see the information as the explanation of the error, but as a hint to where to search. "Misleading" is a bad adjective in this case I think. > This is a general concern for printing the class loader delegation parent. > There is also the specific concern relative to IllegalAccessError, that finding the incorrect class file, may, based on class access, result in an IAE, but more frequently won't be detected here. The causes of these errors are quite manifold. Therefore it is hard to print exactly the information needed to understand it. But leaving out information because it might not be useful in some situations is not a good idea. > 3. Lois has offered to work closely with you on exploring ways to print out the loader type for the unnamed loader case - that information is pertinent to everyone That's great! ... what about a default name for class loaders? Maybe 'loader@<hashcode> instance of <classname>' But also in case of a named loader the name might not be helpful. It might be generated or pointless, just think of "MyLoader". > 4. Independent of this specific RFE, I believe we should explore ways to help your team and others with similar issues to get better information about the mapping between initiating and defining class loaders. I think that is an important design discussion with room for brainstorming, so we can help with the important problem you are trying to solve. Yes, thanks :) To come back to my intended change: You probably saw that in linkResolver.cpp I call loader_name(), and only use describe_external() in classFileParser.cpp. So to continue with the respective change, should I replace the calls to describe_external() in classFileParser.cpp by loader_name()? We will then automatically get better information for unnamed loaders once loader_name is improved for this case? Please notice that the messages modified in classFileParser.cpp are the fallback messages. If the error is related to modules, Reflection::verify_class_access_msg() returns a more precise message. Cheers, Goetz.
23-05-2018

Goetz, had a long talk with Lois and studied your latest changes. 1. Really appreciate that you are working with us to improve the error messages to be more helpful and specifically adding information such as class loader names. 2. Adding the class loader delegation parent is not appropriate for the direction we are going. Specifically as we move to modules, the class loaders may perform direct delegation for classes in packages in named modules in their Layer, only delegating to the class loader delegation parent for classes in packages in the unnamed module. Even today, without modules, we have customers with many class loaders, not all of which follow the delegation parent model. So this information could be misleading since it might not be pertinent to the mapping from initiating class loader to defining class loader. This is a general concern for printing the class loader delegation parent. There is also the specific concern relative to IllegalAccessError, that finding the incorrect class file, may, based on class access, result in an IAE, but more frequently won't be detected here. 3. Lois has offered to work closely with you on exploring ways to print out the loader type for the unnamed loader case - that information is pertinent to everyone 4. Independent of this specific RFE, I believe we should explore ways to help your team and others with similar issues to get better information about the mapping between initiating and defining class loaders. I think that is an important design discussion with room for brainstorming, so we can help with the important problem you are trying to solve.
22-05-2018

In my eyes, the message should contain two kinds of information: 1. What went wrong. 2. Information to locate the failing code. We have systems that have hundred thousands of class loaders, and even more classes loaded. If you get the message: "MyClass1 cannot access MyClass2" there might be several classes of that name. Different parts of your application might use the same library, maybe in different versions so that classes with the same name are loaded several times. Further, you might not be able to get all the Java code that is running at the customer to search it for the classes etc. Having knowledge about the class loader, its parent etc. helps to track down the part of the application that contains the broken classes. So it is not about explaining the error, it is about giving information to locate the error. Maybe it is helpful to split the information not to overload the sentence that gives the cause? But maybe also the modularization helps, as giving the module name as proposed by Mandy might be enough information to spot the proper class. Our experience is with current systems that are on Java before 9. Also, the current messages here as "class test.IAE1_B cannot access its superinterface test.IAE1_A" do not give the real reason, here, why it can not access the superinterface. So I guess there is room for improvement. The message cited by Lois is good, it clearly states the reason for the access failure. It could still mention the precise location of the offending code, but that information is not available I guess.
14-05-2018

For JDK 9 within the JVM we did update IllegalAccessError message to include package & module information in both illegal accessibility and illegal member access cases. The information is included in the message only in the situation were access is denied due to a lack of package exportability or module readability. See test open/test/hotspot/jtreg/runtime/modules/AccessCheckSuper.java. The resulting IAE message: java.lang.IllegalAccessError: superclass access check failed: class p3.c3 (in module module_three) cannot access class p2.c2 (in module module_two) because module module_three does not read module module_two
03-05-2018

Goetz, you mention in an email that having the parent loader included helps with tracking down the problem. Could you please give an example in which you get an IAE for which the parent loader is relevant? Otherwise, I see this as potentially sending people in the wrong direction when they are looking for an explanation. I agree with Mandy that have the module information is very helpful in understanding why they got an IAE.
02-05-2018

I agree with David that class loader information is not relevant here. On the other hand, we should update appropriate IAE with module information as in IAE thrown for illegal class access. JDK 9 has updated IllegalAccessError exception message to the following when it denies access to a class. IllegalAccessException thrown by core reflection is also consistent with IllegalAccessError. class $FROM_CLASS (in $FROM_MODULE) cannot access class $TO_CLASS (in $TO_MODULE) because $TO_MODULE does not export $PACKAGE_OF_TO_CLASS to $FROM_MODULE The format of the module is: if it's a named module, it will print as "module $MODULE" if it's an unnamed module, it will print as "unnamed module @0xnnnnnnnn" where 0xnnnnnnnn is the identity hash code of the module. For illegal member access, we should update IAE to include "in $MODULE" similar to the above consistently. For example, class test.IAE1_B (in unnamed module @0x3d04a311) cannot access its superinterface test.IAE1_A (in module test) Each module is defined to one class loader.
28-03-2018

I do not agree with this change. These message are far too unweildy and just obfuscate the actual error. The classloader information is not relevant here.
21-03-2018