Java:动态加载外部类
我正在编写一个将加载Java脚本的应用程序。我目前有一个GUI,它利用Java:动态加载外部类,java,classpath,classloader,Java,Classpath,Classloader,我正在编写一个将加载Java脚本的应用程序。我目前有一个GUI,它利用JFileChooser允许用户从机器上选择脚本。脚本文件可以在任何地方。它不在类路径上。只有一个文件对象来表示该脚本文件,如何获得它的类表示 我知道加载一个类需要它的二进制名称,所以.this.format中的。然而,问题是,我不知道脚本作者可能是如何将其打包的。例如,在开发脚本文件时,他/她可能会将脚本文件放在包foo.bar中。下载此脚本并将其放入文档(即,不在foo/bar中)后,如果不知道脚本已打包在foo.bar中
JFileChooser
允许用户从机器上选择脚本。脚本文件可以在任何地方。它不在类路径上。只有一个文件
对象来表示该脚本文件,如何获得它的类
表示
我知道加载一个类需要它的二进制名称,所以.this.format中的。然而,问题是,我不知道脚本作者可能是如何将其打包的。例如,在开发脚本文件时,他/她可能会将脚本文件放在包foo.bar
中。下载此脚本并将其放入文档(即,不在foo/bar
中)后,如果不知道脚本已打包在foo.bar
中,则无法加载脚本。如果类名是Test
,我尝试创建一个URLClassLoader
,通过执行newurlclassloader(newurl[]{newurl(scriptFile.toURI().toURL())}
和classLoader.loadClass(“Test”)
来指向脚本文件,我将得到一个异常,说明该类的名称错误,正确的名称是foo.bar.Test
。但我怎么能提前知道呢
这就是我现在拥有的:
public class ScriptClassLoader extends URLClassLoader {
private final File script;
public ScriptClassLoader(File script) throws MalformedURLException {
super(new URL[] { script.toURI().toURL() });
this.script = script;
}
public Class<?> load() throws ClassNotFoundException {
String fileName = script.getName();
String className = fileName.substring(0, fileName.indexOf(".class"));
return loadClass(className);
}
}
公共类ScriptClassLoader扩展了URLClassLoader{
私有最终文件脚本;
公共ScriptClassLoader(文件脚本)引发畸形的异常{
超级(新URL[]{script.toURI().toURL()});
this.script=脚本;
}
public Class load()引发ClassNotFoundException{
字符串文件名=script.getName();
String className=fileName.substring(0,fileName.indexOf(“.class”);
返回loadClass(className);
}
}
人们如何在运行时加载不属于程序类路径的脚本,并且类的二进制名称未知?如果您只需要从给定的.class文件加载类,无论这些类如何命名,您都可以自己加载数据,然后调用ClassLoader的defineClass()
方法:
RandomAccessFile raf = new RandomAccessFile(script, "r");
try {
byte[] classData = new byte[(int) raf.length()];
raf.readFully(classData);
return super.defineClass(null, classData, 0, classData.length);
} finally {
raf.close();
}
这绝不是一个解决方案,但是您可以捕获抛出的异常,读取正确的名称,然后再次执行读取操作。是的,它很便宜,但这是我读到《你》杂志的第一分钟就想到的第一件事。从积极的方面来看,这表明以正确的方式这样做是可能的。还有,请发一封邮件。我也想过这个,但那感觉太便宜了。如果没有更优雅的解决方案,我可能会这样做。实际上有很多解决方案,请参见和初学者。在这种情况下,ScriptClassLoader
甚至不需要扩展URLClassLoader
——它可以直接从ClassLoader
继承。如果主脚本文件引用其他脚本文件,这将如何工作?如果我在foo.bar
中有MainScript
,并且它在foo.bar.other
中引用了SomeOtherScriptClass
,如果我只加载MainScript
,该方法还能工作吗?或者,当脚本的执行到达使用SomeOtherScriptClass
类中的方法的代码时,我是否会得到NodeFoundError
?@MartinTuskevicius来解析对其他类的未知引用JVM将调用类加载器的loadClass()
方法。您必须实现它,以便它在foo/bar/other
或当前目录中或您喜欢的任何位置查找SomeOtherScriptClass.class
。如果不将.class文件放置在预期的位置,那么这就是您要付出的代价。