Search code examples
javareflectionpackageclassloaderjava-9

Is there some method to get all class name under some package of JRE's system module(Java9+),for example java.base


I refer to this article (https://www.baeldung.com/java-find-all-classes-in-package),

under Java11: work only to the package like "com.xxx", if i test "java.util", not work(return 0 size set, see test code below).

under Java8: both work.

test code:

public class AccessingAllClassesInPackage {

    public Set<Class> findAllClassesUsingClassLoader(String packageName) {
        InputStream stream = ClassLoader.getSystemClassLoader()
                .getResourceAsStream(packageName.replaceAll("[.]", "/"));
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        return reader.lines()
                .filter(line -> line.endsWith(".class"))
                .map(line -> getClass(line, packageName))
                .collect(Collectors.toSet());
    }

    private Class getClass(String className, String packageName) {
        try {
            return Class.forName(packageName + "."
                    + className.substring(0, className.lastIndexOf('.')));
        } catch (ClassNotFoundException e) {
            // handle the exception
        }
        return null;
    }

    public Set<Class> findAllClassesUsingReflectionsLibrary(String packageName) {
        Reflections reflections = new Reflections(packageName, new SubTypesScanner(false));
        return reflections.getSubTypesOf(Object.class)
                .stream()
                .collect(Collectors.toSet());
    }

    public Set<Class> findAllClassesUsingGoogleGuice(String packageName) throws IOException {
        return ClassPath.from(ClassLoader.getSystemClassLoader())
                .getAllClasses()
                .stream()
                .filter(clazz -> clazz.getPackageName()
                        .equalsIgnoreCase(packageName))
                .map(clazz -> clazz.load())
                .collect(Collectors.toSet());
    }
}

public class DemoApplication {

    public static void main(String[] args) throws IOException {

        String packageA = "com.google.common.reflect";
        String packageB = "java.util";

        AccessingAllClassesInPackage instance = new AccessingAllClassesInPackage();

        Set<Class> classesA = instance.findAllClassesUsingClassLoader(packageB);

        Set<Class> classesB = instance.findAllClassesUsingReflectionsLibrary(packageB);

        Set<Class> classesC = instance.findAllClassesUsingGoogleGuice(packageB);

        System.out.println("args = " + Arrays.deepToString(args));
    }
}


Solution

  • private static List<Path> findClasses(Path module) throws IOException {
            List<Path> classes = new ArrayList<>();
            Files.walkFileTree(module, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    String fileName = file.getFileName().toString();
                    if (fileName.endsWith(".class") && !fileName.contains("$")) {
                        classes.add(file);
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
            return classes;
        }
    
    FileSystem fileSystem = FileSystems.getFileSystem(URI.create("jrt:/"));
    Path modules = fileSystem.getPath("/modules/java.base/java/util");
    List<Path> classes = findClasses(modules);