有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java动态加载和实例化。不在类路径中的类

我有两个java项目MASTER和PLUGIN。插件依赖于MASTER,其目的是扩展MASTER中的一个类,称为SCRIPT

一旦我声明了一个脚本(myScript),我想移动这个脚本。将文件类设置为MASTER可以访问的文件夹。我想让MASTER动态加载并将该类实例化为脚本

我已经寻找了很多,并尝试了不同的解决方案,但我总是得到一个ClassNotFoundException异常

我更愿意在启动时不向JVM传递参数

有可能吗?这是我当前的解决方案:“currentPath”是“etc/etc/myScript.class”

try {
        OUT.ln("initiating script " + currentPath);
        File file = new File(currentPath);
        File parent = file.getParentFile();

        String name = file.getName().split(".class")[0];


          // Convert File to a URL
        URL url = parent.toURI().toURL();          
        URL[] urls = new URL[]{url};

        // Create a new class loader with the directory
        @SuppressWarnings("resource")
        ClassLoader cl = new URLClassLoader(urls);

        current = (SCRIPT) cl.loadClass("main.script." + name).newInstance();

    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("Unable to load script  " + currentPath);
    }

共 (1) 个答案

  1. # 1 楼答案

    如果要加载的类在包中定义,如:

    main.script.myScript

    你想从c:/myclasses这样的文件夹加载这个类

    然后你必须把这个类放到c:/myclasses/main/script/myScript.class

    然后用basefolder实例化classloader,如下所示:

    URL[] urls = new URL[]{new URL("file://c:/myclasses")};
    ClassLoader cl = new URLClassLoader(urls);
    

    然后可以使用限定的类名加载该类:

    cl.loadClass("main.script.myScript").getDeclaredConstructor().newInstance()
    

    如果您想在不考虑包结构的情况下将类保存在特定文件夹中,可以执行以下操作:

     public static void main(String[] args) {
            try {
    
                File file = new File("etc/etc/myScript.class");
                String className = file.getName().split(".class")[0];
                String packageName = "main.script.";
    
                byte[] bytes = Files.readAllBytes(Path.of(file.getPath()));
                MyClassLoader myClassLoader = new MyClassLoader(Thread.currentThread().getContextClassLoader());
                Object o = myClassLoader.getClass(packageName+className, bytes).getDeclaredConstructor().newInstance();
                System.out.println(o);
    
    
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("Unable to load script  ");
            }
        }
    
        public static class MyClassLoader extends ClassLoader {
            public MyClassLoader(ClassLoader parent) {
                super(parent);
            }
            public Class<?> getClass(String name, byte[] code) {
                return defineClass(name, code, 0, code.length);
            }    
        }