Carsten Jäger
2013-04-19 01:03:43 UTC
Carsten JÀger [https://community.jboss.org/people/aumaster] created the discussion
"Duplicate class definition error on CtClass.toClass() call"
To view the discussion, visit: https://community.jboss.org/message/809164#809164
--------------------------------------------------------------
I'm trying to reflect annotation changes to classes.
When i call the CtClass.toCalls method i always getting 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());
       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 file for the complete sample.
*
*
*
--------------------------------------------------------------
Reply to this message by going to Community
[https://community.jboss.org/message/809164#809164]
Start a new discussion in Javassist at Community
[https://community.jboss.org/choose-container!input.jspa?contentType=1&containerType=14&container=2062]
"Duplicate class definition error on CtClass.toClass() call"
To view the discussion, visit: https://community.jboss.org/message/809164#809164
--------------------------------------------------------------
I'm trying to reflect annotation changes to classes.
When i call the CtClass.toCalls method i always getting 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());
       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 file for the complete sample.
*
*
*
--------------------------------------------------------------
Reply to this message by going to Community
[https://community.jboss.org/message/809164#809164]
Start a new discussion in Javassist at Community
[https://community.jboss.org/choose-container!input.jspa?contentType=1&containerType=14&container=2062]