Override nested class at runtime, is it possible? (java.lang.NoClassDefFoundError: class names do not match)

I have a test class called "InnerClassTransactionServlet", inside this class I have defined an inner class called RandomResultHandler (InnerClassTransactionServlet $ RandomResultHandler).

I'm trying to override an inner class dynamically, but the toolkit returns a "class names do not match" error:

java.lang.NoClassDefFoundError: class names don't match
    at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
    at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
    at com.example.Test.redefineClass(Test.java:33)
    .
    .
    .

      

I tried to override the include class but I get the same error.

The method responsible for overriding is very simple:

public static void redefineClass(ClassDefinition definition) throws ClassNotFoundException, UnmodifiableClassException{
        log.debug("Trying to redefine class "+definition.getDefinitionClass().getName());
        Agent.getInstrumentation().redefineClasses(definition);
}

      

The "definition" parameter is just a ClassDefinition object, defined with the class name and the compilation result byte:

log.debug("Class "+clazz.getName()+" compiled properly. Trying to replace the bytecode in memory.");
ClassDefinition cd = new ClassDefinition(clazz, compilationResult);
redefineClass(cd);

      

Using exactly the same code to override non-nested classes (or classes without nested classes) it works great.

Do you know if it is possible to override nested classes or classes that contain nested classes?

Thank!!

+3


source to share


1 answer


Finally, I was able to find the problem :)

It is necessary to override nested classes at the same time except the attached one. It is not possible to override just a nested class.

So, I changed the redefinition method to get multiple ClassDefinition objects:



public static void redefineClasses(ClassDefinition... definition) throws ClassNotFoundException, UnmodifiableClassException{
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < definition.length; i++) {
            if ( sb.length() > 0 )
                sb.append(", ");
            sb.append(definition[i].getDefinitionClass().getName());
        }

        log.debug("Trying to redefine class"+(definition.length>1?"es ":" ")+sb);
        Agent.getInstrumentation().redefineClasses(definition);
    }

      

So now to override my inner class, I call this method with the class definition "InnerClassTransactionServlet" and "InnerClassTransactionServlet $ RandomResultHandler" and the code has been replaced correctly.

+2


source







All Articles