ACC_DEPRECATED flag (or corresponding attribute) is lost if the constant pool is copied
If the ACC_DEPRECATED flag is set on a method by a ClassVisitor and the constant pool is copied, the Deprecated
attribute will not be set in the resulting class file. For a simple reproduction, execute the following code:
ClassWriter init = new ClassWriter(0);
init.visit(Opcodes.V1_4, Opcodes.ACC_ABSTRACT, "foo/Bar", null, "java/lang/Object", null);
init.visitMethod(Opcodes.ACC_ABSTRACT, "qux", "()V", null, null).visitEnd();
init.visitEnd();
ClassReader classReader = new ClassReader(init.toByteArray());
// If the constant pool is copied, the deprecation flag is not set in the resulting class file.
ClassWriter transformed = new ClassWriter(classReader, 0);
// ClassWriter transformed = new ClassWriter(0);
classReader.accept(new ClassVisitor(Opcodes.ASM6, transformed) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
access |= Opcodes.ACC_DEPRECATED;
return super.visitMethod(access, name, desc, signature, exceptions);
// As a workaround, one can trick ASM to not copy the original method's attributes:
// return new MethodVisitor(Opcodes.ASM6, super.visitMethod(access, name, desc, signature, exceptions)) {};
}
}, 0);
new ClassReader(transformed.toByteArray()).accept(new TraceClassVisitor(new PrintWriter(System.out)), 0);
If the classReader
is provided to the ClassWriter
, the attribute implied by ACC_DEPRECATED
will not be displayed in the resulting print out whereas it is added if the constant pool is created from scratch by new ClassWriter(0)
.
The problem is the short cut that is applied by MethodWriter::computeMethodInfoSize
which detects visitors coming from a ClassWriter
. I think that ASM should detect that ACC_DEPRECATED
was set and avoid the shortcut in this case without needing to work around.