2012-03-21 50 views
2

我有一个ClassLoader,它从源文件加载由JavaCompiler编译的类。 但是,当我更改源文件,保存并重新编译它时,ClassLoader仍然加载该类的第一个版本。Java类加载器:加载两次相同的类

ClassLoader cl = Thread.currentThread().getContextClassLoader(); 
    Class<?> compiledClass = cl.loadClass(stringClass); 

我在想什么?像newInstance什么的?

回答

10

类加载器无法替换已经加载的类。 loadClass将返回现有Class实例的参考。

你将不得不实例化一个新的类加载器并使用它来加载新的类。然后,如果你想“替换”这个类,你必须把这个类加载器扔掉,并创建另一个新类。


在回答您的评论(县):这样做

ClassLoader cl = new UrlClassLoader(new URL[]{pathToClassAsUrl}); 
Class<?> compiledClass = cl.loadClass(stringClass); 

这个类加载器将使用“默认的代理父类加载器”,你必须照顾,类(由它确定完全限定的类名)尚未加载,并且不能由该父类加载器加载。所以“pathToClassAsUrl”不应该在类路径中!

+0

如何在我的方法中替换或删除ClassLoader? – ctekk 2012-03-21 12:48:47

+0

另外:如果我写一个自定义ClassLoader,它会工作吗? – ctekk 2012-03-21 12:57:54

+0

谢谢你,我在这里发现了你的评论的一个很好的解释:http://www.exampledepot.com/egs/java.lang/reloadclass.html – ctekk 2012-03-26 09:36:40

1

您每次都必须加载一个新的ClassLoader,或者每次给这个类指定一个不同的名称并通过接口访问它。

例如

interface MyWorker { 
    public void work(); 
} 

class Worker1 implement MyWorker { 
    public void work() { /* code */ } 
} 

class Worker2 implement MyWorker { 
    public void work() { /* different code */ } 
} 
+0

如何每次使用相同的方法加载新的ClassLoader? – ctekk 2012-03-21 13:24:19

+0

你可以创建一个新的ClassLoader(),你可以通过调用defineClass来触发它来加载类。 – 2012-03-21 18:49:37

+0

新的Classloader()不能像这样启动。 – ctekk 2012-03-22 09:07:10

0

我认为这个问题可能比其他答案的建议更基础。类加载器很可能会加载与您认为不同的文件。为了测试这个理论,删除.class文件(不要重新编译你的.java源文件)并运行你的代码。你应该得到一个例外。

如果你没有得到异常,那么很显然,类加载器正在加载一个不同于你认为的那个.class文件。因此,搜索具有相同名称的另一个.class文件的位置。删除该.class文件并重试。继续尝试,直到找到实际加载的.class文件。一旦你这样做,你可以重新编译你的代码,并手动将类文件放在正确的目录中。

+0

但上面的答案表明,一旦加载类,类加载器不会再从文件加载它。这似乎是适当的行为。我也想到了。 – ctekk 2012-03-22 09:06:17