Repository navigation
Crash on LexForge 48.0.32-48.1.0(?) when using java agent that loads URL class early #12
Description
Operating System
Windows
Version of Prism Launcher
Prism Launcher 9.4
Version of Qt
Qt 6.8.1
Description of bug
I'm using a java agent, and when I in the premain call code which loads java.net.URL before LexForge initializes, I get the following error when my premain invokes code that initializes java.net.URL:
java.lang.IllegalStateException: Package cpw/mods/niofs/union for module cpw.mods.securejarhandler is already in the unnamed module defined to the class loader
at java.base/java.lang.Module.defineModule0(Native Method)
at java.base/java.lang.Module.<init>(Module.java:137)
at java.base/java.lang.Module.defineModules(Module.java:1183)
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
at io.github.zekerzhayard.forgewrapper.installer.util.ModuleUtil.addModules(ModuleUtil.java:92)
at io.github.zekerzhayard.forgewrapper.installer.Bootstrap.bootstrap(Bootstrap.java:66)
at io.github.zekerzhayard.forgewrapper.installer.Main.main(Main.java:55)
at org.prismlauncher.launcher.impl.StandardLauncher.launch(StandardLauncher.java:105)
at org.prismlauncher.EntryPoint.listen(EntryPoint.java:129)
at org.prismlauncher.EntryPoint.main(EntryPoint.java:70)
Followed by this crash not long after:
Exception caught from launcher
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:569)
at io.github.zekerzhayard.forgewrapper.installer.Main.main(Main.java:67)
at org.prismlauncher.launcher.impl.StandardLauncher.launch(StandardLauncher.java:105)
at org.prismlauncher.EntryPoint.listen(EntryPoint.java:129)
at org.prismlauncher.EntryPoint.main(EntryPoint.java:70)
Caused by: java.lang.Error: factory already defined
at java.base/java.net.URL.setURLStreamHandlerFactory(URL.java:1228)
at net.minecraftforge.securemodules.SecureModuleClassLoader.setupModularURLHandler(SecureModuleClassLoader.java:50)
at net.minecraftforge.securemodules.SecureModuleClassLoader.<clinit>(SecureModuleClassLoader.java:44)
at net.minecraftforge.bootstrap.BootstrapLauncher.main(BootstrapLauncher.java:117)
... 8 more
Exiting with ERROR
This problem does not occur on LexForge 48.0.31 or prior, but more importantly, this issue does not occur while using the vanilla launcher. I have been unable to test 1.20.3 on Prism (see #11 for that), but on 1.20.4 running the lowest possible version of LexForge not affected by #11, 49.0.4, this issue does not occur. I assume that this therefore affects 48.0.32 up to 48.1.0 (the last 48.x release), and that it stops triggering under LexForge 49, though only up to 48.1.0 is available for 1.20.2.
Steps to reproduce
- Create a 1.20.2 instance
- Install any version of LexForge above 48.0.31
- Add a java agent that loads java.net.URL in premain to the instance (maybe a dummy
new URL()) - Launch the game
Suspected cause
I assume that the cause is a combination of changes made in LexForge 48.0.32 to the securejarhandler, and more relevantly to Prism Launcher, some sort of flaw with Prism's launch wrapper. That is why this issue should be fixed within Prism, because Prism's launch wrapper is the primary cause for the breakage and the issue does not manifest when using the vanilla launcher.
I asked Lex about this and he speculated the following:
Yup thats Prism not implementing the module system correctly
You'd have to ask them
NIO FileSystems CANT go into a module layer they HAVE to be on the boot class/module path.
The wrapper adding them to a new module is wrong.
This issue is unique
- I have searched the issue tracker and did not find an issue describing my bug.
Activity
Trial97 commentedon Dec 7, 2025
Can you specify which Java agent you are using?
As from my testing, the only way to achieve this is if the jar agent does something like
Class<?> clazz = Class.forName(className);and loads the class with one method, then the ForgeWrapper/Forge Installer loads the same class via import.TheKodeToad commentedon Dec 7, 2025
Instead of whatever we've got going on here https://github.com/PrismLauncher/ForgeWrapper/blob/master/jigsaw/src/main/java/io/github/zekerzhayard/forgewrapper/installer/util/ModuleUtil.java maybe we should just pass the arguments directly to java (this wasn't possible in multimc which upstream forgewrapper was made for)
I don't really understand Java modules but I imagine what we're doing which involves sun.misc.Unsafe and other internals is a pretty bad idea
This does seem like an edge case so it might take a while to be fixed... (though I have hoped we can remove the jigsaw hacks for a while)
catfromplan9 commentedon Dec 8, 2025
I believe it is due to this?
catfromplan9 commentedon Dec 8, 2025
I appreciate that you're taking the time to think of solutions for this issue, and I understand why this is low priority. Yeah, Lex seems to agree that what you are doing is a bad idea. I am very novice when it comes to java, so I am curious why is it necessary for Prism Launcher to always use a launch wrapper. Do you mind explaining?
Trial97 commentedon Dec 8, 2025
Well, Prism uses the wrapper as we need to somehow extract the libraries into a different folder.
With Vanilla Minecraft launcher, when Forge installs itself, it does so in
.minecraftfolder, but because Prism needs to support multiple instances, this installation needs to happen inlibraries, which is outside the instance root folder.Forge installer doesn't support that by default, so we need the wrapper to point the install to there.
Trial97 commentedon Dec 8, 2025
Can you see if you can reproduce it with: https://github.com/PrismLauncher/files/blob/master/maven/io/github/zekerzhayard/ForgeWrapper/prism-2025-07-01/ForgeWrapper-prism-2025-07-01.jar
To test this:
librariesfolder from your instance (you can access that folder from instance version settings on the left side there is one libraries)<instance root>/patches/net.forge.json(the name may differ so I will update it later)If this works, then it's a regression on our side because we needed to add the URL in #10 . If this fails may not be fixable
catfromplan9 commentedon Dec 8, 2025
nope, same crash:
when I try to access URL early, then a moment later
however on the most up-to-date ForgeWrapper the secondary error is different, please ignore the secondary error I initially attached this issue, it was a mistake on my end with my java agent, this is what I actually get when just accessing URL:
catfromplan9 commentedon Dec 8, 2025
actually the secondary error seems to vary each time, so nvm about it being different between ForgeWrappers, but it is always some sort of
x not known to this layer