我正在使用Javassist(Java 1.7)向类ClassA添加注释,但我得到了异常。我究竟做错了什么?我试过的代码看起来像这样:
ClassA.java
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;
}
致电
Class<ClassA> addXmlRootAnnotationDynamicly = addXmlRootAnnotationDynamicly(ClassA.class);
异常
javassist.CannotCompileException:by java.lang.LinkageError:loader(sun / misc / Launcher $ AppClassLoader的实例):尝试重复的名称类定义:“de / it_p / pvlight / share / util / ClassA” at javassist.ClassPool.toClass(ClassPool.java:1099) at javassist.ClassPool.toClass(ClassPool.java:1042) at javassist.ClassPool.toClass(ClassPool.java:1000) at javassist.CtClass.toClass(CtClass.java:1224) at de.it_p.pvlight.share.util.JAXBUtil.addXmlRootAnnotationDynamicly(JAXBUtil.java:107) at de.it_p.pvlight.share.util.JAXBUtilTest.addXmlRootAnnotationDynamicly(JAXBUtilTest.java:60) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.lang.reflect.Method.invoke(Method.java:606) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at 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” at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:800) at java.lang.ClassLoader.defineClass(ClassLoader.java:643) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.lang.reflect.Method.invoke(Method.java:606) at javassist.ClassPool.toClass2(ClassPool.java:1112) at javassist.ClassPool.toClass(ClassPool.java:1093) ......还有15个
答案 0 :(得分:11)
问题的根源可以在堆栈跟踪中找到:
尝试重复的名称类定义:&#34; de / it_p / pvlight / share / util / ClassA&#34;
您的addXmlRootAnnotationDynamicly
方法需要加载类,并重新定义此类,而不更改其名称。在重新定义之后,您将再次尝试加载已更改的类。但是,在Java中,ClassLoader
only load a class of a given name one single time可以Instrumentation API。
出于这个原因,pool.getCtClass
方法使用String
代替加载的Class
,并使用用于描述卸载的CtClass
es Class
es。为了解决您的问题,您有不同的选择:
addXmlRootAnnotationDynamicly(String)
并传递de.it_p.pvlight.share.util.ClassA
作为参数。在代码中的任何位置转换之前,请确保未加载此类。因此,您应该在应用程序的启动时运行转换,以确保在转换之前不会意外加载该类。然后,您在Class
上加载了已更改的cc.toClass()
。ClassLoader
s。 (不推荐)