classgraph / classgraph

An uber-fast parallelized Java classpath scanner and module scanner.
MIT License
2.73k stars 285 forks source link

Catch `NoClassDefFoundError` when loading methods #879

Closed freya022 closed 3 weeks ago

freya022 commented 3 weeks ago

Those happen if the method returns an unknown type, I also added documentation for the IllegalArgumentException thrown when loading parameter classes

lukehutch commented 3 weeks ago

Great contribution, thanks. I'll check if FieldInfo and ClassInfo need the same treatment.

lukehutch commented 3 weeks ago

@freya022 OK, so I handled this a different way, by moving the try...catch in the loadClass method instead -- please check the latest git version and let me know if this resolves the issue you were seeing, without the extra catch phrases that you added.

freya022 commented 3 weeks ago

@freya022 OK, so I handled this a different way, by moving the try...catch in the loadClass method instead -- please check the latest git version and let me know if this resolves the issue you were seeing, without the extra catch phrases that you added.

The extra catch was necessary because the exception is thrown when loading the method, the return type of the method is never loaded by ClassGraph, and so it must be loaded by the VM when getting the method, here's the stack trace I get, with my changes it would have been wrapped in an IllegalArgumentException, but with your changes, it isn't:

Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/boot/context/event/ApplicationReadyEvent
    at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3578)
    at java.base/java.lang.Class.getMethodsRecursive(Class.java:3719)
    at java.base/java.lang.Class.getMethod0(Class.java:3705)
    at java.base/java.lang.Class.getMethod(Class.java:2393)
    at io.github.classgraph.MethodInfo.loadClassAndGetMethod(MethodInfo.java:668)
    at com.freya02.bot.Main.main(Main.kt:34)
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.event.ApplicationReadyEvent
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
    ... 7 more

The method loaded is public ApplicationReadyEvent test(), and is in an external library where the dependency for this class is optional

lukehutch commented 3 weeks ago

Ah, of course, your original change even said that in the comments. Thanks, I'll add the catch back again.

freya022 commented 3 weeks ago

Ah, of course, your original change even said that in the comments. Thanks, I'll add the catch back again.

I don't think adding it for the constructor is necessary, it returns itself, which is already loaded at this point, and the superclasses would be checked by the VM

lukehutch commented 3 weeks ago

@freya022 Good catch, thanks.

lukehutch commented 3 weeks ago

Released in 4.8.175. Thank you!