jboss-javassist / javassist

Java bytecode engineering toolkit
www.javassist.org
Other
4.1k stars 695 forks source link

failed to add interface to generic class #371

Open ted-wq-x opened 3 years ago

ted-wq-x commented 3 years ago

make a class UDF2

public abstract class UDF2<BUF> {
    public abstract void reset(BUF buf);
}

create a interface called com.daml.dti.function.Function ,Make UDF2 implement the interface

ClassPool pool = ClassPool.getDefault();
CtClass function = pool.makeInterface("com.daml.dti.function.Function");
CtClass udf = pool.get(UDF2.class.getName());
udf.addInterface(function);
udf.debugWriteFile();

the result is wrong:

package com.daml.dti.function;

public abstract class UDF2<BUF> {
  public abstract void reset(BUF paramBUF);
}

when i delete the generic

ClassPool pool = ClassPool.getDefault();
CtClass function = pool.makeInterface("com.daml.dti.function.Function");
CtClass udf = pool.get(UDF2.class.getName());
udf.addInterface(function);
ClassFile classFile = udf.getClassFile();
classFile.removeAttribute("Signature");
udf.debugWriteFile();

the result is correct.

package com.daml.dti.function;

public abstract class UDF2 implements Function {
  public abstract void reset(BUF paramBUF);
}
ted-wq-x commented 3 years ago

i found a solution,When the class is generic, need to modify the class genericSignature.

 ClassFile classFile = udf.getClassFile();
  SignatureAttribute signature = (SignatureAttribute) classFile.getAttribute("Signature");
  SignatureAttribute.ClassSignature toClassSignature = SignatureAttribute.toClassSignature(signature.getSignature());

  SignatureAttribute.ClassType[] interfaces = toClassSignature.getInterfaces();
  SignatureAttribute.ClassType[] copy = Arrays.copyOf(interfaces, interfaces.length + 1);
  copy[interfaces.length] = new SignatureAttribute.ClassType("com.daml.dti.function.Function");
  SignatureAttribute.ClassSignature newSignature = new SignatureAttribute.ClassSignature(toClassSignature.getParameters(),
          toClassSignature.getSuperClass(), copy);
  udf.setGenericSignature(newSignature.encode());