使用Javassist向运行时生成的类添加注释
我正在使用Javassist(Java1.7)向类ClassA添加注释,但我得到了一个异常。我做错了什么?我尝试的代码如下所示: ClassA.java使用Javassist向运行时生成的类添加注释,java,annotations,javassist,Java,Annotations,Javassist,我正在使用Javassist(Java1.7)向类ClassA添加注释,但我得到了一个异常。我做错了什么?我尝试的代码如下所示: ClassA.java public class ClassA { } 添加方法 public static <T> Class<T> addXmlRootAnnotationDynamicly(Class<T> declaredTyp) throws NotFoundException, CannotCompileExcept
public class ClassA
{
}
添加方法
public static <T> Class<T> addXmlRootAnnotationDynamicly(Class<T> declaredTyp) throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException
{
//pool creation
ClassPool pool = ClassPool.getDefault();
//extracting the class
CtClass cc = pool.getCtClass(declaredTyp.getCanonicalName());
// create the annotation
ClassFile ccFile = cc.getClassFile();
ConstPool constpool = ccFile.getConstPool();
AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
Annotation annot = new Annotation("javax.xml.bind.annotation.XmlRootElement", constpool);
attr.addAnnotation(annot);
// add the annotation to the class
cc.getClassFile().addAttribute(attr);
// transform the ctClass to java class
Class<T> dynamiqueBeanClass = cc.toClass();
//instanciating the updated class
// T sayHelloBean = dynamiqueBeanClass.newInstance();
return dynamiqueBeanClass;
}
公共静态类addXmlRootAnnotationDynamicly(类declaredTyp)抛出NotFoundException、CannotCompileException、InstanceionException、IllegaAccess Exception
{
//池创建
ClassPool=ClassPool.getDefault();
//提取类
CtClass cc=pool.getCtClass(declaredTyp.getCanonicalName());
//创建注释
ClassFile ccFile=cc.getClassFile();
ConstPool ConstPool=ccFile.getConstPool();
AnnotationsAttribute attr=新的AnnotationsAttribute(constpool,AnnotationsAttribute.visibleTag);
Annotation annot=new注释(“javax.xml.bind.Annotation.XmlRootElement”,constpool);
属性添加注释(注释);
//将注释添加到类中
cc.getClassFile().addAttribute(attr);
//将ctClass转换为java类
类dynamicquebeanclass=cc.toClass();
//实例化更新的类
//T sayHelloBean=dynamiqueBeanClass.newInstance();
返回动态类;
}
召唤
Class addXmlRootAnnotationDynamicly=addXmlRootAnnotationDynamicly(ClassA.Class);
例外情况
javassist.cannotcompileeException:by java.lang.LinkageError:loader(sun/misc/Launcher$AppClassLoader的实例):尝试复制名称的类定义:“de/it_p/pvlight/share/util/ClassA”
位于javassist.ClassPool.toClass(ClassPool.java:1099)
位于javassist.ClassPool.toClass(ClassPool.java:1042)
位于javassist.ClassPool.toClass(ClassPool.java:1000)
位于javassist.CtClass.toClass(CtClass.java:1224)
位于de.it_p.pvlight.share.util.JAXBUtil.addXmlRootAnnotationDynamicly(JAXBUtil.java:107)
在de.it_p.pvlight.share.util.JAXBUtilTest.addXmlRootAnnotationDynamicly(JAXBUtilTest.java:60)
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
位于java.lang.reflect.Method.invoke(Method.java:606)
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
位于java.lang.reflect.Method.invoke(Method.java:606)
位于org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
位于org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
位于org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
原因:java.lang.LinkageError:loader(sun/misc/Launcher$AppClassLoader的实例):尝试为名称重复类定义:“de/it_p/pvlight/share/util/ClassA”
位于java.lang.ClassLoader.defineClass1(本机方法)
位于java.lang.ClassLoader.defineClass(ClassLoader.java:800)
位于java.lang.ClassLoader.defineClass(ClassLoader.java:643)
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
位于java.lang.reflect.Method.invoke(Method.java:606)
位于javassist.ClassPool.toClass2(ClassPool.java:1112)
位于javassist.ClassPool.toClass(ClassPool.java:1093)
... 还有15个
可以在堆栈跟踪中找到问题的根源: 尝试为名称复制类定义:“de/it\p/pvlight/share/util/ClassA” 您的
addXmlRootAnnotationDynamicly
方法接受一个加载的类,并在不更改其名称的情况下重新定义这个非常相同的类。在重新定义之后,您将再次尝试加载修改过的类。然而,这在Java中是不可能的,因为任何人都可以
因此,pool.getCtClass
方法采用字符串而不是加载的类
,并与CtClass
es一起工作,后者用于描述卸载的类
es。要解决您的问题,您有不同的选择:
- 将方法的签名更改为
addXmlRootAnnotationDynamicly(String)
,并将de.it\u p.pvlight.share.util.ClassA
作为参数传递。确保在转换该类之前,未在代码中的任何位置加载该类。因此,您应该在应用程序启动时运行转换,以确保在转换之前不会意外加载该类。然后将更改后的类
加载到cc.toClass()
- 创建使用随机名称的参数类(或使用接口)的子类。然后,子类与参数类的类型兼容,但从未加载
- 使用在运行时重新定义加载的类
- 确保输入类和输出类加载了不同的
ClassLoader
s。(不推荐)
Class<ClassA> addXmlRootAnnotationDynamicly = addXmlRootAnnotationDynamicly(ClassA.class);