JBoss Community

Duplicate class definition error on CtClass.toClass() call

created by Carsten Jäger in Javassist - View the full discussion

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

Start a new discussion in Javassist at Community