我在春季项目中获得了以下课程
interface IStep {
IStep doStep();
String getName();
}
@Component
public class Step1 implements IStep {
public final static String NAME = "STEP1";
...
}
@Component
public class Step1 implements IStep {
...
}
从该项目构建了一个 jar。
使用一个简单的java项目,我尝试加载jar来分析类之间的依赖关系并创建一些图表。我的第一个用例是找到所有实现 IStep 的类并获取它们的名称。
我正在尝试使用反射来加载 jar,获取类并加载它们。然而,我总是在
noclassdeffounderror
上得到 Step1
。当我删除 @Component
注释时,它工作得很好。如何在不删除注释的情况下加载类?
JarFile jarFile = new JarFile(pathToJar);
Enumeration<JarEntry> e = jarFile.entries();
URL[] urls = { new URL("jar:file:" + pathToJar+"!/") };
URLClassLoader cl = URLClassLoader.newInstance(urls);
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
if(je.isDirectory() || !je.getName().endsWith(".class") || !je.getName().contains("mypackagename")){
continue;
}
// -6 because of .class
String className = je.getName().substring(0,je.getName().length()-6);
className = className.replace('/', '.');
Class c = cl.loadClass(className); //noclassdeffounderror
}
添加类似 System.out.println(je.getName()); 的内容在 if 表达式之后并显示输出吗?
@AndrewL 我得到这样的东西:
BOOT-INF.classes.com.example.demo.Step1
所以问题出在 jar 文件内的路径上。
试试这个:
我尝试过,但这给了我一个 ClassNotFoundException。
啊,现在我明白了!我事先没看清楚。
是的,如果在 jar 文件(或文件系统)中找不到该类,您将得到
ClassNotFoundException
。但如果存在依赖性问题,您将得到类似名称的 NoClassDefFoundError
。
您遇到的问题是,您的 Jar 文件似乎是由 Spring Boot 在其特殊的“可执行 Jar 文件结构”中创建的。这会在 jar 文件中以分层方式定位依赖项。 一个简单的标准 URLClassLoader 不知道如何查找
embedded jar 文件中的依赖项,这就是为什么你会得到 NoClassDefFoundError
。
可执行 Jar 文件结构