Search code examples
javaclassloader

Java Classloader not working when running jar


I have this Java code, to get all classes in a package:

public static Set<Class> findAllClassesUsingClassLoader(String packageName) throws Exception {
        InputStream stream = ClassLoader.getSystemClassLoader().getResourceAsStream(packageName.replaceAll("[.]", "/"));
        System.out.println(packageName);
        String text = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
        System.out.println(text);
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        return reader.lines().filter(line -> line.endsWith(".class")).map(line -> {
            try {
                System.out.println("HERE");
                return getClass(line, packageName);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }).collect(Collectors.toSet());
    }

    public static Class getClass(String className, String packageName) throws Exception {
        try {
            return Class.forName(packageName + "." + className.substring(0, className.lastIndexOf('.')));
        } catch (ClassNotFoundException e) {
            throw new Exception("Class " + className + " not found!");
        }
    }

It works when I run it from the IDE, but when I run my application with java -jar the InputStream is empty.

How can I change my code in order to make it work running it with java -jar?


Solution

  • I found a solution to the problem:

    Here's the code:

    public static Set<Class<?>> getClassesFromResource(String packageName) throws Exception {
        String packageFolder = packageName.replaceAll("[.]", "/");
        Set<Class<?>> classes = new HashSet<Class<?>>();
        URI resource = EntityDAOUtils.class.getClassLoader().getResource(packageFolder).toURI();
        Path myPath = null;
    
        if ("jar".equals(resource.getScheme())) {
            for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
                if (provider.getScheme().equalsIgnoreCase("jar")) {
                    try {
                        myPath = provider.getFileSystem(resource).getPath(packageFolder);
                    } catch (FileSystemNotFoundException e) {
                        // in this case we need to initialize it first:
                        myPath = provider.newFileSystem(resource, Collections.emptyMap()).getPath(packageFolder);
                    }
                }
            }
        }
    
        Stream<Path> walk = Files.walk(myPath, 1);
        for (Iterator<Path> it = walk.iterator(); it.hasNext();) {
            String line = it.next().toString();
            if (line.endsWith(".class")) {
                classes.add(getClass(line.replace('/', '.').replace(".class", ""), packageName));
            }
        }
        walk.close();
        return classes;
    }
    
    public static Class getClass(String className, String packageName) throws Exception {
        try {
            return Class.forName(packageName + "." + className.substring(className.lastIndexOf('.') + 1));
        } catch (ClassNotFoundException e) {
            throw new Exception(
                    "Class " + packageName + "." + className.substring(className.lastIndexOf('.') + 1) + " not found!");
        }
    }