I'm using guava's ClassPath to retrieve available classes. With Java 8, this worked well, but I'm migrating to Java 10, and now it doesn't work. I've tried both guava 24.1 (the latest jarfile available on Maven Central) and the latest sources on github (as of April 27th 2018) -- presumably more or less guava 25.0, given they released it yesterday.
I can retrieve some classes, but anything in any java.*
packages fail to appear. Is this is actually a bug, or am I using Java 10 wrong (i.e., does modularity mean I need to do something special)? I see the same symptom in Java 9. I've tried building and running with Java 10 (or 9) as well as building with Java 8 and running with Java 10 (or 9), the behaviour is the same either way.
I've set up a dummy example with two classes in packages com.just.me
and com.just.another
:
package com.just.me;
import com.google.common.reflect.ClassPath;
import com.just.another.Dummy;
import java.lang.String;
import java.util.Collections;
import java.util.List;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
List<String> dummyList = Collections.emptyList();
printClassCount("com.just.me", Main.class);
printClassCount("com.just.another", Main.class);
printClassCount("com.just", Main.class);
printClassCount("com.google", Main.class);
printClassCount("java.lang", Main.class);
printClassCount("java.util", Main.class);
printClassCount("java", Main.class);
}
private static void printClassCount(String packageName, Class classForClassLoader) {
System.out.println("Number of toplevel classes in " + packageName + ": " + countTopleveClassesInPackage(packageName, classForClassLoader));
}
private static int countTopleveClassesInPackage(String packageName, Class clazz) {
try {
ClassPath classPath = ClassPath.from(clazz.getClassLoader());
return classPath.getTopLevelClassesRecursive(packageName).size();
} catch (IOException e) {
return 0;
}
}
}
package com.just.another;
public class Dummy {
private String s;
Dummy(String s) {
this.s = s;
}
@Override
public String toString() {
return s;
}
}
Number of toplevel classes in com.just.me: 1
Number of toplevel classes in com.just.another: 1
Number of toplevel classes in com.just: 2
Number of toplevel classes in com.google: 569
Number of toplevel classes in java.lang: 232
Number of toplevel classes in java.util: 367
Number of toplevel classes in java: 1878
Number of toplevel classes in com.just.me: 1
Number of toplevel classes in com.just.another: 1
Number of toplevel classes in com.just: 2
Number of toplevel classes in com.google: 569
Number of toplevel classes in java.lang: 0
Number of toplevel classes in java.util: 0
Number of toplevel classes in java: 0
I think, there is no bug in ClassPath
. It represents a classpath but system classes are not on the classpath in Java 10:
// doesn't print rt.jar because there is no rt.jar anymore
System.out.println(StandardSystemProperty.JAVA_CLASS_PATH.value());
So this is correct behavior that getTopLevelClasses
does not return any classes for the java.*
package.
If you still want to list top-level system classes, you can do something like that (not exact code, just a sketch):
FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
Files
.list(fs.getPath("modules", "java.base", "java/lang"))
.map(Path::getFileName)
.filter(p -> p.toString().endsWith(".class") && !p.toString().contains("$"))
.forEach(System.out::println);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With