What is the correct way to scan classes in other jars?
See original GitHub issueI have a project into which i shaded classgraph-4.8.150, JDK version 16.
The project comes with this method to find certain classes:
public static @NotNull List<Class<? extends CustomItem>> findCustomItemClasses(final @NotNull ClassLoader classLoader, final @NotNull String rootPackagePath) {
final List<Class<? extends CustomItem>> customItemClasses = new ArrayList<>();
try (final ScanResult scanResult = new ClassGraph()
.acceptPackages(rootPackagePath)
.scan()
) {
for (final ClassInfo classInfo : scanResult.getAllClasses()) {
final Class<?> clazz;
try {
clazz = classLoader.loadClass(classInfo.getName());
} catch (ClassNotFoundException ignore) {
continue;
}
if (CustomItem.class.equals(clazz)
|| !CustomItem.class.isAssignableFrom(clazz)
|| !clazz.isAnnotationPresent(CustomItemIdentifier.class)) {
continue;
}
//noinspection unchecked
customItemClasses.add((Class<? extends CustomItem>) clazz);
}
}
return customItemClasses;
}
(Note: of course i used debug sout
s to check if any classes were found at all, even before the filter conditions)
The problem is that this method will only find results within in its native project (in that instance “de.jaylawl.commonljb”). If i am calling this method with any other package path, there are no results.
I have tried many different configurations for ClassGraph
instantiation, but it never works.
But it used to work before, when i was using a prior version of classgraph. I think it was somewhere around 4.8.~50
, when #whitelistPackages
was not deprecated yet.
What am i doing wrong? I’ve been reading through the documentation but i can’t find any examples for what i’m supposed to do for my use case (iterate classes in external jars).
Issue Analytics
- State:
- Created 10 months ago
- Comments:15 (8 by maintainers)
Top GitHub Comments
ClassGraph obtains classpath elements from classloaders, and then scans them manually. Here you can see that
org.bukkit.plugin.java.PluginClassLoader
reported only one jar,CommonLjb.jar
. SincePluginClassLoader
extendsURLClassLoader
, ClassGraph just uses the standardURLClassLoader
API to get the classpath, which contains just that one element.However, it’s possible that this classloader has a different field or method for getting the full set of plugin paths. You will have to find a reference to this classloader in your runtime environment, and then use a debugger to see where inside this classloader the other plugins are stored.
I don’t know how to set up bukkit etc., so I can’t really help you debug this, but a debugger should help you figure it out. You may need to look at other classloaders too.
Once you figure out where the plugin paths are stored, then we can figure out why ClassPath doesn’t detect them.
OK, thanks. Well the output of
toString()
doesn’t contain an address for the object instance for these twoPluginClassLoader
instances, so actually I can’t tell from the output if these are the same instance, but they probably are, sinceurl
points to the same jar.Your original log showed that ClassGraph did in fact find one
PluginClassLoader
. I just can’t understand why it only found one jar, whereas if you manually add thePluginClassLoader
, it finds many more jars.I’m not really sure what else I can suggest unless you want to produce a small reproducer project. Otherwise, at least you have a solution for your purposes. Thanks!