2014-03-28 75 views
0

我正在编写一个将加载Java脚本的应用程序。我目前有一个GUI,它利用JFileChooser来允许用户从他们的机器中选择一个脚本。脚本文件可以在任何地方。它不在类路径中。如果只有一个File对象来表示该脚本文件,我如何才能获得它的Class表示形式?Java:动态加载外部类

我知道,要加载一个类,你需要它的二进制名称,所以in.this.format。然而,问题在于我不知道脚本编写者可能如何打包它。例如,他/她在开发它时可能会将脚本文件放在包foo.bar中。在我下载该脚本并将其放入我的文档中(即而不是foo/bar中)后,我无法加载脚本而不知道它被打包在foo.bar中。如果班级名称是Test,并且我尝试通过执行new URLClassLoader(new URL[] { new URL(scriptFile.toURI().toURL()) })并且我做了classLoader.loadClass("Test")来创建指向脚本文件的URLClassLoader,并且我做了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); 
    } 
} 

人们如何加载在运行时是不是程序的类路径的一部分脚本和类的二进制名称是不知道?

+1

这是不意味着解决方案,但您可以捕获抛出的异常,读取正确的名称,然后再次执行读取操作。是的,这很便宜,但这是我第一次读到你的问题时想到的第一件事。从积极的方面来看,它表明可以以正确的方式做到这一点。另外,请发布[MCVE](http://stackoverflow.com/help/mcve)。 – user1803551

+0

我也想过这个,但觉得太便宜了。如果没有更优雅的解决方案,我可以这样做。 –

+0

实际上有很多解决方案,请参阅[这里](http://stackoverflow.com/questions/11016092/how-to-load-classes-at-runtime-from-a-folder-or-jar)和[这里] (http://stackoverflow.com/questions/20586067/how-to-load-unknown-class-from-downloaded-jar-file-during-runtime)首发。 – user1803551

回答

1

如果你只是需要从给定的.class文件加载类,不管这个班是如何命名的,你可以自己加载数据,然后调用类加载器的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(); 
} 
+0

在这种情况下,'ScriptClassLoader'甚至不需要扩展'URLClassLoader' - 它可以直接从'ClassLoader'继承。 – apangin

+0

如果主脚本文件引用其他脚本文件,这将如何工作?如果我在'foo.bar'中有'MainScript',并且它引用''foo.bar.other'中的'SomeOtherScriptClass',那么如果我只加载'MainScript',该方法是否仍然有效?或者当脚本的执行达到利用'SomeOtherScriptClass'类中的方法的代码时,我会得到一个'NoDefFoundError'? –

+1

@MartinTuskevicius为了解析对其他类的未知引用,JVM将调用你的ClassLoader的'loadClass()'方法。你必须实现它,以便它会在'foo/bar/other'或当前目录或你喜欢的任何地方寻找'SomeOtherScriptClass.class'。如果您没有将.class文件放在预期的位置,那么这就是您付出的代价。 – apangin