使用类加载器重新加载代码时遇到的Java问题
我最近发表了一篇文章,在花了几个小时摆弄不同的示例代码和阅读教程之后,我遇到了以下问题: 通过使用类加载器,我能够在运行时使用处的代码将本地变量从类使用类加载器重新加载代码时遇到的Java问题,java,class,classloader,reloading,Java,Class,Classloader,Reloading,我最近发表了一篇文章,在花了几个小时摆弄不同的示例代码和阅读教程之后,我遇到了以下问题: 通过使用类加载器,我能够在运行时使用处的代码将本地变量从类MyVar1更改为类MyVar2,但我无法用另一个版本的MyVar2替换该类MyVar2 MyVar1和MyVar2都实现了一个接口VarInterface。main类使用类型VarInterface保存变量的实例 我读过其他几个声称正确的实现,但我无法让它工作。有人知道我做错了什么吗 主类循环: while(true){
MyVar1
更改为类MyVar2
,但我无法用另一个版本的MyVar2
替换该类MyVar2
MyVar1
和MyVar2
都实现了一个接口VarInterface
。main类使用类型VarInterface
保存变量的实例
我读过其他几个声称正确的实现,但我无法让它工作。有人知道我做错了什么吗
主类循环:
while(true){
i++;
Thread.sleep(1000);
ui.ping();
if(i > 3)
replaceVar();
}
替换变量:
ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
Class newClass = classLoader.loadClass("MyVar2");
ui = (VarInterface)newClass.newInstance();
MyClassLoader.loadClass:
public Class<?> loadClass(String what){
// Get the directory (URL) of the reloadable class
URL[] urls = null;
try {
// Convert the file object to a URL
File dir = new File(System.getProperty("user.dir")
+File.separator+"dir"+File.separator);
URL url = dir.toURL();
urls = new URL[]{url};
} catch (MalformedURLException e) {
}
// Create a new class loader with the directory
ClassLoader cl = new URLClassLoader(urls);
// Load in the class
Class cls = null;
try {
cls = cl.loadClass("MyVar2");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return cls;
}
公共类loadClass(字符串what){
//获取可重载类的目录(URL)
URL[]URL=null;
试一试{
//将文件对象转换为URL
File dir=新文件(System.getProperty(“user.dir”)
+File.separator+“dir”+File.separator);
URL=dir.toURL();
URL=新URL[]{URL};
}捕获(格式错误){
}
//使用目录创建一个新的类加载器
ClassLoader cl=新的URLClassLoader(URL);
//课堂上的负荷
类别cls=null;
试一试{
cls=cl.loadClass(“MyVar2”);
}catch(classnotfounde异常){
e、 printStackTrace();
}
返回cls;
}
对于前3次迭代,调用了
MyVar1.ping()
,之后调用了MyVar2.ping()
,即使我替换了MyVar2.class
和MyVar2.java
文件。我猜您使用的是两个类加载器。一个是系统类加载器,其中包含大量代码。自定义类加载器将系统类加载器用作其父类。您正试图让自定义类加载器替换系统类加载器中的类。事实上,自定义类装入器将优先于装入自己的类而委托给父类
您需要做的是确保系统类加载器不加载类的任何实现。创建一个类加载器,加载类的实现并委托给系统类加载器。要更改实现,请创建类加载器的另一个实例
(使用
java.net.URLClassLoader.newInstance
创建自己的类加载器实现可能更容易。)我设法解决了这个问题。我忘记了将文件保留在类路径之外,这使得类加载器仅在它属于实现相同接口的不同类时读取新实例,而不是在我用不同版本替换该类时读取新实例
因此,基本上:问题是通过从项目中删除文件并在外部编辑它们来解决的。只是为了澄清这个问题-让我们说
MyVar2.ping()
打印“Hello”,当i==10
将类更改为打印“再见”时,您的问题是无论发生什么更改,您仍然会看到“Hello”,对吧?有点类似。我没有用另一个版本(如I==10)替换MyVar2的内部触发器,我只是直接替换文件或在eclipse中编辑并保存。我正在创建一个新的类加载器实例,正如您在上面的replaceVar函数中看到的那样。“大部分代码”由MyVar类中的循环和ping()
函数组成,因为目前这只是一个沙箱实验。如果这是解决方案,你应该自己接受,这样你的问题显然已经得到了回答(尽管是你自己)。