【发布时间】:2014-05-13 02:57:24
【问题描述】:
我在运行时替换 jar 时遇到了一些问题。我创建了 2 个 jar 都命名为 A.jar,这个 jar 只包含一个名为 A.class 的类,A.class 的代码很简单,第一个 jar 是:System.out.println("before replacement"),第二个 jar 是:System.out.println("after replacement"),我想在运行时用第二个jar替换第一个jar,所以我把第一个jar放在C:下,第二个jar放在C:\test\下
我的代码是:
import java.lang.reflect.Method;
public class B {
public static void main(String[] args) throws Exception{
final String src = "C:\\test\\A.jar";
final String desc = "C:\\";
System.out.println("start to copy A.jar");
String cmd = "cmd /c xcopy " + src + " " + desc + " /y";
Runtime.getRuntime().exec(cmd).waitFor();
System.out.println("finish to copy A.jar");
Class<?> cls = Class.forName("A");
Object obj = cls.newInstance();
Method m = cls.getMethod("test");
m.invoke(obj, null);
/*A a = new A();
a.test();*/
}
}
我发现了 2 个问题:
- 我在eclipse中运行代码,结果是
"after replacement",没问题。但是当我使用命令行运行相同的代码时,它会抛出ClassNotFoundException。命令行有什么问题? -
在eclipse中我替换Java反射代码时
Class<?> cls = Class.forName("A"); Object obj = cls.newInstance(); Method m = cls.getMethod("test"); m.invoke(obj, null);与
A a = new A(); a.test();输出为
"before replacement"。我认为A类应该在运行时加载,所以当new A()类应该首先加载时,当时jar已经被替换,为什么输出仍然"before replacement"和jave反射代码工作正常?
请给我一些指示。谢谢!
添加更多, 我使用 -verbose:class 打印所有类加载信息,我发现对于 class.forname,A.jar 在替换完成后加载,而对于 new A(),A.jar 在我的代码 System.out 之间加载成功。 println("开始复制 A.jar") 和 System.out.println("完成复制 A.jar")。这是因为结果不同。但是为什么 A.jar 在 new A() 之前加载?
【问题讨论】:
-
你知道你发布了
B.java吗?不管怎样,类加载器已经加载了B——又是什么A? -
这可能会有所帮助 - stackoverflow.com/a/6477846/738746
-
我找到了根本原因,问题2是我的JDK用jrockit引起的,我把jrockit换成SUN jdk后,结果还是一样,jrockit的classload顺序和SUN的不一样.
标签: java classloader