Error spamming log
0Navis0 opened this issue ยท 9 comments
This error keep spamming the log during the game loading.
[07:25:07] [ForkJoinPool.commonPool-worker-3/ERROR]: Could not find parent software/bernie/shadowed/fasterxml/jackson/databind/util/PrimitiveArrayBuilder for class software/bernie/shadowed/fasterxml/jackson/databind/util/ArrayBuilders$DoubleBuilder in classloader jdk.internal.loader.ClassLoaders$AppClassLoader@4e0e2f2a on thread Thread[ForkJoinPool.commonPool-worker-3,5,main]
[07:25:07] [ForkJoinPool.commonPool-worker-3/ERROR]: An error occurred building event handler
java.lang.ClassNotFoundException: software.bernie.shadowed.fasterxml.jackson.databind.util.PrimitiveArrayBuilder
at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) ~[?:?]
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) ~[?:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:522) ~[?:?]
at net.minecraftforge.eventbus.EventSubclassTransformer.buildEvents(EventSubclassTransformer.java:62) ~[eventbus-4.0.0.jar:?]
at net.minecraftforge.eventbus.EventSubclassTransformer.transform(EventSubclassTransformer.java:44) ~[eventbus-4.0.0.jar:?]
at net.minecraftforge.eventbus.EventBusEngine.processClass(EventBusEngine.java:21) ~[eventbus-4.0.0.jar:?]
at net.minecraftforge.eventbus.service.ModLauncherService.processClassWithFlags(ModLauncherService.java:20) ~[eventbus-4.0.0.jar:4.0.0+65+master.6080a3f]
at cpw.mods.modlauncher.LaunchPluginHandler.offerClassNodeToPlugins(LaunchPluginHandler.java:85) ~[modlauncher-8.0.9.jar:?]
at cpw.mods.modlauncher.ClassTransformer.transform(ClassTransformer.java:120) ~[modlauncher-8.0.9.jar:?]
at cpw.mods.modlauncher.TransformingClassLoader$DelegatedClassLoader.findClass(TransformingClassLoader.java:265) ~[modlauncher-8.0.9.jar:?]
at cpw.mods.modlauncher.TransformingClassLoader.loadClass(TransformingClassLoader.java:136) ~[modlauncher-8.0.9.jar:?]
at cpw.mods.modlauncher.TransformingClassLoader.loadClass(TransformingClassLoader.java:98) ~[modlauncher-8.0.9.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:522) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.util.ArrayBuilders.getDoubleBuilder(ArrayBuilders.java:78) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$DoubleDeser.deserialize(PrimitiveArrayDeserializers.java:900) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$DoubleDeser.deserialize(PrimitiveArrayDeserializers.java:872) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1608) ~[?:?]
at software.bernie.shadowed.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1216) ~[?:?]
at software.bernie.geckolib3.geo.raw.pojo.Converter.fromJsonString(Converter.java:63) ~[?:?]
at software.bernie.geckolib3.file.GeoModelLoader.loadModel(GeoModelLoader.java:21) ~[?:?]
at software.bernie.geckolib3.resource.GeckoLibCache.lambda$null$9(GeckoLibCache.java:85) ~[?:?]
at java.util.concurrent.CompletableFuture$UniAccept.tryFire(CompletableFuture.java:714) [?:?]
at java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:479) [?:?]
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) [?:?]
at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1016) [?:?]
at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1665) [?:?]
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1598) [?:?]
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183) [?:?]
cc: @cpw who was looking into this yesterday
The crux of this issue comes from the fact it only manifests itself with Java 9+, this has only been working on Java 8 from an implementation detail of ForkJoinPool
. The issue itself is one of classloading, why mod code is trying to be read from the classpath rather than the mod classloader, but it is how EventSubclassTransformer#buildEvents
is classloading which is especially relevant. It tries to load the parent type of the actively loaded class to see if it is an Event
subclass, and does so directly referencing the current thread's context classloader. As this is from the context of ForkJoinPool
's common pool, what that context classloader actually is depends on what the JRE has decided it should be.
On Java 8, with system property java.util.concurrent.ForkJoinPool.common.threadFactory
unset and no security manager used, the common pool's ForkJoinWorkerThreadFactory
is ForkJoinPool#defaultForkJoinWorkerThreadFactory
(see ForkJoinPool#makeCommonPool()
). That default thread factory is ForkJoinPool$DefaultForkJoinWorkerThreadFactory
:
static final class DefaultForkJoinWorkerThreadFactory implements ForkJoinWorkerThreadFactory {
@Override
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return new ForkJoinWorkerThread(pool);
}
}
These ForkJoinWorkerThread
s will inherit the context classloader from that of the thread which makes them, i.e. the mod classloader in this case.
After Java 8 ForkJoinPool#makeCommonPool()
moved to ForkJoinPool#<init>(byte)
, but otherwise works the same way. What doesn't work the same way is ForkJoinPool$DefaultForkJoinWorkerThreadFactory
:
private static final class DefaultForkJoinWorkerThreadFactory implements ForkJoinWorkerThreadFactory {
private static final AccessControlContext ACC = contextWithPermissions(
new RuntimePermission("getClassLoader"),
new RuntimePermission("setContextClassLoader")
);
@Override
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public ForkJoinWorkerThread run() {
return new ForkJoinWorkerThread(pool, ClassLoader.getSystemClassLoader());
}
}, ACC);
}
}
These ForkJoinWorkerThread
s will not inherit the context classloader from that of the thread which makes them, but instead the system classloader.
From here it seems quite clear what has happened, with the common pool threads now using the system classloader the event transformer has no chance of finding the parent types, hence the exceptions. (In case it was not clear the common pool is being used from the CompletableFuture
s in GeckoLibCache#resourceReload
) Why it doesn't happen more frequently/at all is possibly just a result of mods having already loaded any types before the common pool might use them (if they're using the common pool at all which most mods wouldn't be).
As it happens having helped with unrelated debugging on ForgeCraft I had rewritten GeckoLibCache#resourceReload
in a way which probably fixes this. Not to say that's the only way to fix it, quite the contrary, but using the resource loading Executor
s is arguably the best and simplest fix for what you're doing.
This should be resolved in the latest update. If a user of Java 9+ could please test the newest version and respond here as I don't have Java 9+ myself. If I hear nothing in a week, I'll go ahead and close this issue.
@Chocohead I don't understand 90% of this but thank you for the help! I'll edit GeckoLibCache
to have your changes. Thanks a ton!
Thanks for the help @Chocohead and @cpw I'll be implementing your suggested fix here tonight into the main branches. Thanks again for the awesome help!