"duplicate class definition" error on CtClass.toClass() call
aumaster Apr 18, 2013 9:27 PMI'm trying to reflect annotation changes to classes.
When i call the CtClass.toClass() method i'm always getting the following error:
javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "ReflectionTest"
Googl'ing for a solution, told me to provide an own ClassLoader when calling the toClass() method. But i found no sample how to implement it...
This is my Testcase:
1.) The class to modify:
import javax.persistence.Table;
@Table(name="xyz")
public class ReflectionTest {
}
2.) The test class:
import java.util.ArrayList;
import java.util.Collection;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.StringMemberValue;
import javax.persistence.Table;
public class ReflectionSample {
public static void main(final String[] args) {
/*
* It's no solution to provide just the class names as a string,
* what will only work, if no application part accessed the classes already.
*/
final Collection<Class<?>> classes = new ArrayList<Class<?>>();
classes.add(ReflectionTest.class);
doReflection(classes);
final ReflectionTest test = new ReflectionTest();
final Table table = test.getClass().getAnnotation(Table.class);
System.out.println("name : " + table.name()); // Expecting: "xyz"
System.out.println("schema: " + table.schema()); // Expecting: "TestSchema"
}
private static void doReflection(final Collection<Class<?>> classes) {
final ClassPool classPool = ClassPool.getDefault();
for (final Class<?> clazz : classes) {
try {
final CtClass ctClass = classPool.get(clazz.getName());
final ConstPool constPool = ctClass.getClassFile().getConstPool();
final AnnotationsAttribute attribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
final Table table = (Table) ctClass.getAnnotation(Table.class);
final Annotation tableAnnotation = new Annotation("javax.persistence.Table", constPool);
tableAnnotation.addMemberValue("name", new StringMemberValue(table.name(), constPool));
tableAnnotation.addMemberValue("schema", new StringMemberValue("TestSchema", constPool));
attribute.addAnnotation(tableAnnotation);
ctClass.getClassFile().addAttribute(attribute);
// This throws a java.lang.LinkageError ... attempted duplicate class definition for name: "ReflectionTest"!
ctClass.toClass();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Any help is appreciated!
Tia, Carsten
P.S.: See attached ZIP for the source files...
-
sample.zip 1.1 KB