执行 Java AnnotationProcessor 时出现 ClassNotFound 异常
ClassNotFound exception while executing Java AnnotationProcessor
我写了一个简单的注释和一个 AnnotationProcessor 来处理注释。
注释只有一个值:它应该是现有接口的名称(带包)。
注释处理器应该检索注释的值,检索接口的 Class 对象,最后应该打印接口中声明的所有方法。
示例:
这是我的注释
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation{
public String interfaceName();
}
这是注释 class:
@MyAnnotation(interfaceName = "java.lang.CharSequence")
public class Example{}
我的处理器看起来像
[...]
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
for (TypeElement te : annotations) {
for(Element e : env.getElementsAnnotatedWith(te)) {
MyAnnotation myAnnotation = e.getAnnotation(MyAnnotation.class);
String iName = myAnnotation.interfaceName();
Class<?> clazz = Class.forName(iName);
// use reflection to cycle through methods and prints them
[...]
}
}
现在,如果我将 java.lang.CharSequence 之类的接口配置为 MyAnnotation 的 interfaceName,则可以正常工作;
但是,如果我将位于 .jar 文件(添加到项目的构建路径中)中的接口配置为 interfaceName,我会在尝试执行 Class.forName 时获得 ClassNotFoundException (...) 声明。
有什么想法吗?
谢谢,
干杯
这是典型的类加载器问题。您正在尝试查找当前 class 加载程序未加载的 class,因此抛出 ClassNotFoundException
。
java.lang.Class
的 Javadoc 将方法 Class.forName(className)
定义为:
Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to Class.forName(className, true, currentLoader)
where currentLoader denotes the defining class loader of the current class.
因此,此方法调用将尝试在当前 class 加载程序上下文中查找指定的 class。此 classloader 尚未加载您尝试查找的接口,因此抛出 ClassNotFoundException
。
如果 .jar
文件位于应用程序的 class 路径中,您可以简单地使用系统 classloader,就像这样...
ClassLoader systemClassLoader = ClassLoader.getSystemClassloader();
Class<?> clazz = Class.forName(className, true, systemClassLoader)
...但是如果您的 .jar
文件位于其他地方,并且尚未加载,您将需要相应地加载它:
ClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("path/to/file.jar")});
Class<?> clazz = Class.forName(className, true, urlClassLoader)
瞧瞧!
我写了一个简单的注释和一个 AnnotationProcessor 来处理注释。
注释只有一个值:它应该是现有接口的名称(带包)。
注释处理器应该检索注释的值,检索接口的 Class 对象,最后应该打印接口中声明的所有方法。
示例: 这是我的注释
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation{
public String interfaceName();
}
这是注释 class:
@MyAnnotation(interfaceName = "java.lang.CharSequence")
public class Example{}
我的处理器看起来像
[...]
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
for (TypeElement te : annotations) {
for(Element e : env.getElementsAnnotatedWith(te)) {
MyAnnotation myAnnotation = e.getAnnotation(MyAnnotation.class);
String iName = myAnnotation.interfaceName();
Class<?> clazz = Class.forName(iName);
// use reflection to cycle through methods and prints them
[...]
}
}
现在,如果我将 java.lang.CharSequence 之类的接口配置为 MyAnnotation 的 interfaceName,则可以正常工作;
但是,如果我将位于 .jar 文件(添加到项目的构建路径中)中的接口配置为 interfaceName,我会在尝试执行 Class.forName 时获得 ClassNotFoundException (...) 声明。
有什么想法吗?
谢谢, 干杯
这是典型的类加载器问题。您正在尝试查找当前 class 加载程序未加载的 class,因此抛出 ClassNotFoundException
。
java.lang.Class
的 Javadoc 将方法 Class.forName(className)
定义为:
Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to
Class.forName(className, true, currentLoader)
where currentLoader denotes the defining class loader of the current class.
因此,此方法调用将尝试在当前 class 加载程序上下文中查找指定的 class。此 classloader 尚未加载您尝试查找的接口,因此抛出 ClassNotFoundException
。
如果 .jar
文件位于应用程序的 class 路径中,您可以简单地使用系统 classloader,就像这样...
ClassLoader systemClassLoader = ClassLoader.getSystemClassloader();
Class<?> clazz = Class.forName(className, true, systemClassLoader)
...但是如果您的 .jar
文件位于其他地方,并且尚未加载,您将需要相应地加载它:
ClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("path/to/file.jar")});
Class<?> clazz = Class.forName(className, true, urlClassLoader)
瞧瞧!