mercredi 31 juillet 2019

Launch JavaFX project using reflection

I have a program, that downloads a Git repository, builds it and launches defined Main class. It works properly with ordinary projects, but when I want to launch a JavaFX project, I get strange errors like:

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at Main.main(Main.java:31)
Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: app.UI_Main
    at javafx.application.Application.launch(Application.java:260)
    at app.UI_Main.main(UI_Main.java:31)
    ... 5 more
Caused by: java.lang.ClassNotFoundException: app.UI_Main
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at javafx.application.Application.launch(Application.java:248)
    ... 6 more

My Main class is:

public class Main {
    private static final String GIT_ADDRESS = "https://github.com/lerryv/CheckCheckerDesktop";
    private static final String MAIN_PATH = "app/";
    private static final String MAIN_CLASS = "app.UI_Main";
    public static void main(String[] args) throws GitAPIException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Git.cloneRepository().setURI(GIT_ADDRESS).setDirectory(Paths.get("./dir/").toFile()).call();
        Collection<String> result = compile(Paths.get("./dir/src/").toFile());
        String command = System.getProperty("java.home") + "/../bin/javac -d dirOut -cp \".:json-simple-1.1.jar\" " + result.join(" ");
        Runtime.getRuntime().exec(command);
        URLClassLoader urlClassLoader = URLClassLoader.newInstance(
                new URL[]{
                        new File("dirOut/").toURI().toURL()
                }
        );
        Class clazz = urlClassLoader.loadClass(MAIN_CLASS);
        Method main = clazz.getDeclaredMethod("main", String[].class);
        assert Modifier.isStatic(main.getModifiers());
        main.invoke(null, (Object) args);
    }
    private static Collection<String> compile(File directory) {
        assert directory.isDirectory();
        Collection<String> result = new Collection<>();
        boolean hasFiles = false;
        for (File file: directory.listFiles()) {
            if (file.isDirectory()) {
                result.addAll(compile(file));
            } else {
                if (!hasFiles) {
                    String path = file.getAbsolutePath();
                    String extension = path.substring(path.lastIndexOf(".") + 1);
                    if (extension.equals("java")) hasFiles = true;
                }
            }
        }
        if (hasFiles) result.add(directory.getAbsolutePath() + "/*.java");
        return result;
    };
}

At first I thought it cannot find the class, but when I removed the method.invoke statement, errors disappeared. Why does it happen and are there any workarounds?





Aucun commentaire:

Enregistrer un commentaire