I want to use ASM to verify how often certain methods are called and what their arguments and result is. However, at runtime it ends with a java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "com/foo/bar/DefaultType"
.
For that reason I want to ensure that it is not an ASM (Objectweb) problem, so it tried to just pass the bytes without any modification with the following code:
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException {
byte[] result;
if(className.startsWith("com/foo/bar"))
{
ClassReader reader = new ClassReader(classfileBuffer);
try
{
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
reader.accept(writer, 0);
result = writer.toByteArray();
}
catch(Exception e)
{
result = null;
}
}
else
{
// do nothing
result = null;
}
return result;
}
But even after this modification I get the same Error. Any hints what I should change to get this code working?
Late answer to an old question.
One way these errors can occur is due to how the
COMPUTE_FRAMES
option ofClassWriter
is implemented. In particular, the frame computation will sometimes need to figure out a common superclass for two given classes; to do this, it will load the classes it is interested in usingClass.forName
. If your codebase uses a non-trivial class loading setup, it may happen that a class gets loaded in an unpexected class loader this way (I can't recall the precise conditions, but I have had this happen to me). The solution is to override thegetCommonSuperclass
method ofClassWriter
to perform the same computation in a safer way.