0

I am using ASM's ClassWriter to duplicate a class. I use reflection to load a class with this duplicated byte code, however when I try to invoke a method of the duplicate class with an instance of the class that was duplicated I get an 'Object is not an instance of declaring class' exception.

Object originalObj = ...
Class<?> originalClass = obj.getClass();
String methodName = ...

ClassReader cr = new ClassReader(originalClass.getName());
ClassWriter cw = new ClassWriter(0);
cr.accept(cw, 0);
DynamicClassLoader loader = new DynamicClassLoader();
Class<?> c = loader.define(originalClass.getName(), cw.toByteArray());
Method m = c.getMethod(methodName); // Assume 'methodName' has no args
m.setAccessible(true);
m.invoke(originalClass.cast(originalObj));
8
  • originalObj is declared as Object and therefore will have no access to your methods. You have to originalClass.cast(...) it to the type to invoke the methods... Commented Mar 13, 2014 at 11:41
  • @GermannArlington thanks for your suggestion but unfortunately the exception still occurs Commented Mar 13, 2014 at 12:07
  • If I try and cast originalObject using c I get a ClassCastException - but c and originalClass have the same bytecode so why is this a problem? Commented Mar 13, 2014 at 12:15
  • 1
    A duplicated class is not the same class. Commented Mar 13, 2014 at 12:16
  • It depends on your DynamicClassLoader and how it's interpretation of this new class differs from the original. Try loading both classes in DynamicClassLoader and see if it recognises them as the same class... Commented Mar 13, 2014 at 12:43

1 Answer 1

3

A loaded Java type is constituted by two parameters:

  1. The type's fully qualified name.
  2. The ClassLoader that was used for loading this type.

This implies that the types [com.example.Foo, ClassLoaderA] and [com.example.Foo, ClassLoaderB] are not equal. You can therefore not cast the first type to the second. Once an instance is created, you simply cannot change its type.

The line

originalClass.cast(originalObj)

does not have any effect since originalObj already is an instance of originalClass. The copied class c is however not assignable to orginalClass, despite the equal name.

Have a look at the Java instrumentation API for changing a class that was already loaded.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.