我正在制作一个用于绘制算法时间复杂度的模拟器。学生可以添加加载自己的.java文件来运行它。 我的程序编译(使用'JavaCompiler').java文件。然后它尝试加载.class文件:
loadedClass = loadClass("customAlgorithms."+this.getClassName()+"");
在Eclipse中运行我的程序时,一切正常,学生可以完美地使用该程序。
然后我将项目导出到可执行jar文件中。编译部分仍然有效但加载类失败,因为它在里面搜索jar文件。
我想知道为什么我不能这样做:(改变。用/)
loadedClass = loadClass("customAlgorithms/"+this.getClassName()+"");
有哪些选择?这就是我能想到的:
将已编译的.class文件添加到当前运行的.jar文件中。这甚至可以工作吗?
我知道可以编辑jar存档。但这可以在运行时运行而无需重新启动程序吗?
使用'loadClass()'的其他方式?这样我就可以加载一个未包含在我的jar文件中的类文件
还有其他想法吗?
答案 0 :(得分:3)
Java通过ClassLoaders加载类。当您启动JVM时,您必须告诉JVM它的“类路径”,即类的文件夹或jar文件列表。 JVM将创建一个ClassLoader(通常是URLClassLoader的子类),并为此ClassLoader提供文件夹和jar文件的列表,以便类加载器能够加载该类。
在您的应用程序中,当您编译java源文件时,它会生成一个保存在某处的类文件。可能在eclipse中,保存类文件的文件夹是包含在类路径中的文件夹,以便JVM能够找到该类。
当您将项目导出到正在运行的jar文件时,可能会启动JVM,其类路径中只包含该JAR文件,因此它不会搜索已编译类的任何其他位置。
您有几种方法可以解决此问题。按复杂程度递增:
解决方案1非常简单,但有它的缺点:如果没有再次运行整个程序,将无法重新加载已编译的java文件(一旦类加载到类加载器中,它就无法再次加载,除非使用超出此问题范围的代理程序),它要求程序写入磁盘,这意味着权限等。
解决方案2及其演变只是RAM更优雅,但更复杂:从类加载器加载单个类不同于整个应用程序其余部分使用的类是很棘手的,你可能会得到奇怪的类异常(如ClassCastExceptions,ClassNotFoundException等..)由于类加载器之间不匹配。
答案 1 :(得分:1)
您可以使用ClassLoader
defineClass method。它受到保护,但应该没有问题。
如果该方法受到保护是一个问题,可能在互联网的某个地方你可以定义一个自由可用的自定义子类。
答案 2 :(得分:1)
您必须创建另一个类加载器,例如URLClassLoader并从中加载该类。