gpt4 book ai didi

java - 在运行时重新加载使用过的类 Java

转载 作者:太空狗 更新时间:2023-10-29 22:57:25 33 4
gpt4 key购买 nike

我正在开发一个程序,它监视目录并在看到目录中的更改时运行目录中的所有测试。

这需要程序动态加载类,而不是获取缓存的副本。

我可以动态加载测试类。在运行时检测并使用对测试的更改。但是,测试所测试的类并非如此。

我的动态加载类并返回测试类列表的代码:

List<Class<?>> classes = new ArrayList<Class<?>>();
for (File file : classFiles) {
String fullName = file.getPath();
String name = fullName.substring(fullName.indexOf("bin")+4)
.replace('/', '.')
.replace('\\', '.');
name = name.substring(0, name.length() - 6);

tempClass = new DynamicClassLoader(Thread.currentThread().getContextClassLoader()).findClass(name) } catch (ClassNotFoundException e1) {
// TODO Decide how to handle exception
e1.printStackTrace();
}

boolean cHasTestMethods = false;
for(Method method: tempClass.getMethods()){
if(method.isAnnotationPresent(Test.class)){
cHasTestMethods = true;
break;
}
}
if (!Modifier.isAbstract(cachedClass.getModifiers()) && cHasTestMethods) {
classes.add(tempClass);
}
}
return classes;

将 DynamicClassLoader 作为此处描述的 Reloader How to force Java to reload class upon instantiation?

知道如何解决吗?我以为所有的类都会被动态加载。但是请注意,我不会在我的 DynamicClassLoader 中覆盖 loadclass,因为如果我这样做,我的测试类会给出 init

编辑:这不起作用,该类已加载但未检测到其中的测试...

List<Request> requests = new ArrayList<Request>();
for (File file : classFiles) {
String fullName = file.getPath();
String name = fullName.substring(fullName.indexOf("bin")+4)
.replace('/', '.')
.replace('\\', '.');
name = name.substring(0, name.length() - 6);
Class<?> cachedClass = null;
Class<?> dynamicClass = null;
try {
cachedClass = Class.forName(name);


URL[] urls={ cachedClass.getProtectionDomain().getCodeSource().getLocation() };
ClassLoader delegateParent = cachedClass .getClassLoader().getParent();
URLClassLoader cl = new URLClassLoader(urls, delegateParent) ;
dynamicClass = cl.loadClass(name);
System.out.println(dynamicClass);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

编辑编辑:我检测到这样的测试方法:

            for(Method method: dynamicClass.getMethods()){
if(method.isAnnotationPresent(Test.class)){
requests.add(Request.method(dynamicClass, method.getName()));
}
}

最佳答案

如果您使用自定义 ClassLoader与链接的答案完全一样,它没有覆盖方法 protected Class<?> loadClass(String name, boolean resolve) .这意味着当 JVM 解析依赖项时,它仍将委托(delegate)给父类加载器。而且,当然,当它没有委托(delegate)给 parent 时 ClassLoader它有错过一些必修课的风险。

最简单的解决方案是设置正确的父类加载器。您目前正在通过 Thread.currentThread().getContextClassLoader()这有点奇怪,因为您的主要意图是委派应该委派给那个加载器,而是加载更改的类。您必须考虑存在哪些类加载器以及使用哪些类加载器,哪些不使用。例如。如果类Foo在您当前代码的范围内,但您想使用新的类加载器(重新)加载它,Foo.class.getClassLoader().getParent()将是新 ClassLoader 的正确委托(delegate)父级.请注意,它可能是 null但这并不重要,因为在这种情况下,它会使用引导加载程序,它是正确的父级。

注意当你设置正确的parent ClassLoader符合您的意图,您不需要那个自定义 ClassLoader了。默认实现(参见 URLClassLoader )已经做了正确的事情。对于当前的 Java 版本,它是 Closeable使其更适合动态加载场景。

这是一个类重新加载的简单示例:

import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;

public class ReloadMyClass
{
public static void main(String[] args)
throws ClassNotFoundException, IOException {
Class<?> myClass=ReloadMyClass.class;
System.out.printf("my class is Class@%x%n", myClass.hashCode());
System.out.println("reloading");
URL[] urls={ myClass.getProtectionDomain().getCodeSource().getLocation() };
ClassLoader delegateParent = myClass.getClassLoader().getParent();
try(URLClassLoader cl=new URLClassLoader(urls, delegateParent)) {
Class<?> reloaded=cl.loadClass(myClass.getName());
System.out.printf("reloaded my class: Class@%x%n", reloaded.hashCode());
System.out.println("Different classes: "+(myClass!=reloaded));
}
}
}

关于java - 在运行时重新加载使用过的类 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20091075/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com