Skip to content

Fix hierarchy computation of boot layer classes#28

Merged
marchermans merged 3 commits into
McModLauncher:mainfrom
Su5eD:fix/cl-resources
May 23, 2022
Merged

Fix hierarchy computation of boot layer classes#28
marchermans merged 3 commits into
McModLauncher:mainfrom
Su5eD:fix/cl-resources

Conversation

@Su5eD
Copy link
Copy Markdown
Member

@Su5eD Su5eD commented Mar 26, 2022

The issue

As reported in #27, ModuleClassLoader fails to read bytes of libraries on the java boot module layer used in transformers. This happens because it's trying to find resources on the PlatformClassLoader instead of the AppClassLoader.
See here for a full explanation of the issue by @sciwhiz12.

The solution

Quote from sciwhiz's explanation:

Therefore, the solution is that the above error be corrected by changing the use of ClassLoader.getPlatformClassLoader() to ClassLoader.getSystemClassLoader() instead, so the resolution of class bytes for ASM, SJH, and BSL (or any other class whose module is in the ignore list configured in BSL and exists on the application class loader) works as expected.

@sciwhiz12 sciwhiz12 added the bug Something isn't working label Mar 26, 2022
@marchermans
Copy link
Copy Markdown
Member

@Su5eD How have you tested that this won't be causing any issues down the line with classpath collisions?

@marchermans marchermans self-assigned this Mar 28, 2022
@marchermans marchermans added this to the MC 1.19 milestone Mar 28, 2022
@marchermans marchermans marked this pull request as draft March 28, 2022 07:13
@Su5eD
Copy link
Copy Markdown
Member Author

Su5eD commented Mar 28, 2022

The system classloader primarily looks for class resources (e.g. those containing a fully qualified class name, such as cpw/mods/niofs/union/UnionFileSystem.class) in the class' module, so the read resource is always identical to the loaded class. In case a class from an unnamed module is used in a transformer, reading it will be successful, although the game will crash if it ever tries to load the class. This, however, shouldn't happen with our current setup.

Alternatively, we can keep the platform classloader and throw a ClassNotFoundException if the resource can not be found, notifying modlauncher to load the class and use computeHierarchyFromClass instead.

@marchermans
Copy link
Copy Markdown
Member

I know how it works, my problem is that the call to ClassLoader.getSystemClassLoader() gives access to a classloader which is not in module mode.
And that is something we should prevent.

@marchermans
Copy link
Copy Markdown
Member

This was talked through on discord:
The proposed change here violates several constraints set by the original design.
However, a proper solution is already in place it is just not properly working.

The current implementation expects the transforming classloader to throw an exception if it could not load the transformed class bytecode, this is not happening, it is just returning an empty array, causing the crash.

Proposal for changes:

  1. Prevent transforms from running on an empty byte array (this is also happening)
  2. Make the transform classloader throw an exception when an empty byte array was loaded from the disk.

This should then enable the intended code path with compatible loading to function again.

Throw ClassNotFoundException if they're not found, remove fallback classloader
Comment on lines +239 to +241
} else if (this.parentLoaders.containsKey(pname)) {
var cname = name.replace('.','/')+".class";
try (var is = this.parentLoaders.getOrDefault(pname, ClassLoader.getSystemClassLoader()).getResourceAsStream(cname)) {
try (var is = this.parentLoaders.get(pname).getResourceAsStream(cname)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed a good idea, since this would else pipe system classes potentially through transformers.
And the call site takes care of this dynamically.

Comment thread src/main/java/cpw/mods/cl/ModuleClassLoader.java Outdated
Comment thread src/main/java/cpw/mods/cl/ModuleClassLoader.java Outdated
@Su5eD Su5eD changed the title Fix reading transformable class bytes loaded by AppClassLoader Fix hierarchy computation of boot layer classes Mar 31, 2022
@marchermans
Copy link
Copy Markdown
Member

This looks much better now, once I figure out how to properly test this stuff, I will pull it out of draft and start the triaging and testing procedure....

@marchermans marchermans marked this pull request as ready for review April 11, 2022 14:23
@marchermans
Copy link
Copy Markdown
Member

Testing procedures have been setup.
Last call for this PR before I merge it in a couple of days.

@marchermans marchermans merged commit 88e0e27 into McModLauncher:main May 23, 2022
@Su5eD Su5eD deleted the fix/cl-resources branch May 27, 2022 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants