[Legacy] GeckoLib Fabric

[Legacy] GeckoLib Fabric

3M Downloads

Error spamming log

0Navis0 opened this issue ยท 9 comments

commented

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) [?:?]
commented

This still requires attention

commented

Same as me, but only happen when I use JDK 8+ to start the game.

commented

Yeah it happens only when using a java version upper than 8.

commented

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 ForkJoinWorkerThreads 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 ForkJoinWorkerThreads 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 CompletableFutures 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 Executors is arguably the best and simplest fix for what you're doing.

commented

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.

commented

@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!

commented

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!

commented

I just tried, it seems to work now, I don't get more the error.

commented

Alright! Closing this issue now