use of javassist.bytecode.CodeAttribute in project fakereplace by fakereplace.
the class Transformer method addConstructorForInstrumentation.
private void addConstructorForInstrumentation(ClassFile file) {
MethodInfo ret = new MethodInfo(file.getConstPool(), "<init>", Constants.ADDED_CONSTRUCTOR_DESCRIPTOR);
Bytecode code = new Bytecode(file.getConstPool());
// if the class does not have a constructor return
if (!ManipulationUtils.addBogusConstructorCall(file, code)) {
return;
}
CodeAttribute ca = code.toCodeAttribute();
ca.setMaxLocals(4);
ret.setCodeAttribute(ca);
ret.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.SYNTHETIC);
try {
ca.computeMaxStack();
file.addMethod(ret);
} catch (DuplicateMemberException e) {
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of javassist.bytecode.CodeAttribute in project fakereplace by fakereplace.
the class Transformer method addMethodForInstrumentation.
/**
* Adds a method to a class that re can redefine when the class is reloaded
*/
private void addMethodForInstrumentation(ClassFile file) {
try {
MethodInfo m = new MethodInfo(file.getConstPool(), Constants.ADDED_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
m.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.SYNTHETIC);
Bytecode b = new Bytecode(file.getConstPool(), 5, 3);
if (BuiltinClassData.skipInstrumentation(file.getSuperclass())) {
b.addNew(NoSuchMethodError.class.getName());
b.add(Opcode.DUP);
b.addInvokespecial(NoSuchMethodError.class.getName(), "<init>", "()V");
b.add(Opcode.ATHROW);
} else {
// delegate to the parent class
b.add(Bytecode.ALOAD_0);
b.add(Bytecode.ILOAD_1);
b.add(Bytecode.ALOAD_2);
b.addInvokespecial(file.getSuperclass(), Constants.ADDED_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
b.add(Bytecode.ARETURN);
}
CodeAttribute ca = b.toCodeAttribute();
m.setCodeAttribute(ca);
file.addMethod(m);
} catch (DuplicateMemberException e) {
// e.printStackTrace();
}
try {
MethodInfo m = new MethodInfo(file.getConstPool(), Constants.ADDED_STATIC_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
m.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC | AccessFlag.SYNTHETIC);
Bytecode b = new Bytecode(file.getConstPool(), 5, 3);
b.addNew(NoSuchMethodError.class.getName());
b.add(Opcode.DUP);
b.addInvokespecial(NoSuchMethodError.class.getName(), "<init>", "()V");
b.add(Opcode.ATHROW);
CodeAttribute ca = b.toCodeAttribute();
m.setCodeAttribute(ca);
file.addMethod(m);
} catch (DuplicateMemberException e) {
// e.printStackTrace();
}
}
use of javassist.bytecode.CodeAttribute in project fakereplace by fakereplace.
the class MethodReplacementTransformer method generateBoxedConditionalCodeBlock.
/**
* This method will take a method body and add it to an added method local
* the bytecode is inserted inside a conditional that will only run the code
* if the method number is correct variables are removed from the parameter
* array and unboxed if nessesary the return value is boxed if nessesary
* <p>
* Much of this work is handled by helper classes
*/
private static void generateBoxedConditionalCodeBlock(int methodNumber, MethodInfo mInfo, ConstPool methodConstPool, CodeAttribute addedMethod, boolean staticMethod, boolean constructor) throws BadBytecode {
// we need to insert a conditional
Bytecode bc = new Bytecode(mInfo.getConstPool());
CodeAttribute ca = (CodeAttribute) mInfo.getCodeAttribute().copy(mInfo.getConstPool(), Collections.emptyMap());
if (staticMethod) {
bc.addOpcode(Opcode.ILOAD_0);
} else {
bc.addOpcode(Opcode.ILOAD_1);
}
int methodCountIndex = methodConstPool.addIntegerInfo(methodNumber);
bc.addLdc(methodCountIndex);
bc.addOpcode(Opcode.IF_ICMPNE);
// now we need to fix local variables and unbox parameters etc
int addedCodeLength = mangleParameters(staticMethod, constructor, ca, mInfo.getDescriptor());
int newMax = ca.getMaxLocals() + 2;
if (constructor) {
// for the extra
newMax++;
}
if (newMax > addedMethod.getMaxLocals()) {
addedMethod.setMaxLocals(newMax);
}
// later
int offset = ca.getCodeLength();
// offset is +3, 2 for the branch offset after the IF_ICMPNE and 1 to
// take it past the end of the code
// add the branch offset
ManipulationUtils.add16bit(bc, offset + 3);
// now we need to insert our generated conditional at the start of the
// new method
CodeIterator newInfo = ca.iterator();
newInfo.insert(bc.get());
// now insert the new method code at the beginning of the static method
// code attribute
addedMethod.iterator().insert(ca.getCode());
// update the exception table
int exOffset = bc.length() + addedCodeLength;
for (int i = 0; i < mInfo.getCodeAttribute().getExceptionTable().size(); ++i) {
int start = mInfo.getCodeAttribute().getExceptionTable().startPc(i) + exOffset;
int end = mInfo.getCodeAttribute().getExceptionTable().endPc(i) + exOffset;
int handler = mInfo.getCodeAttribute().getExceptionTable().handlerPc(i) + exOffset;
int type = mInfo.getCodeAttribute().getExceptionTable().catchType(i);
addedMethod.getExceptionTable().add(start, end, handler, type);
}
// rewriteFakeMethod makes sure that the return type is properly boxed
if (!constructor) {
rewriteFakeMethod(addedMethod.iterator(), mInfo.getDescriptor());
}
}
use of javassist.bytecode.CodeAttribute in project fakereplace by fakereplace.
the class MethodReplacementTransformer method createRemovedMethod.
private static MethodInfo createRemovedMethod(ClassFile file, MethodData md, Class<?> oldClass, Set<MethodData> methodsToRemove) {
if (md.getMethodName().equals("<clinit>")) {
// if the static constructor is removed it gets added later on
return null;
// in the process
}
// load up the existing method object
MethodInfo m = new MethodInfo(file.getConstPool(), md.getMethodName(), md.getDescriptor());
m.setAccessFlags(md.getAccessFlags());
// put the old annotations on the class
if (md.getMethodName().equals("<init>")) {
Constructor<?> meth;
try {
meth = md.getConstructor(oldClass);
} catch (Exception e) {
throw new RuntimeException("Error accessing existing constructor via reflection in not found", e);
}
m.addAttribute(AnnotationReplacer.duplicateAnnotationsAttribute(file.getConstPool(), meth));
} else {
Method meth;
try {
meth = md.getMethod(oldClass);
} catch (Exception e) {
throw new RuntimeException("Error accessing existing method via reflection in not found", e);
}
m.addAttribute(AnnotationReplacer.duplicateAnnotationsAttribute(file.getConstPool(), meth));
}
Bytecode b = new Bytecode(file.getConstPool(), 5, 3);
b.addNew("java.lang.NoSuchMethodError");
b.add(Opcode.DUP);
b.addInvokespecial("java.lang.NoSuchMethodError", "<init>", "()V");
b.add(Bytecode.ATHROW);
CodeAttribute ca = b.toCodeAttribute();
m.setCodeAttribute(ca);
try {
ca.computeMaxStack();
file.addMethod(m);
} catch (DuplicateMemberException e) {
logger.error("Duplicate error", e);
} catch (BadBytecode e) {
logger.error("Bad bytecode", e);
}
methodsToRemove.add(md);
return m;
}
use of javassist.bytecode.CodeAttribute in project yyl_example by Relucent.
the class GetMethodParamNameTest method getMethodParamNames.
/**
* 获得参数名 (JDK 自带类 ,接口方法和抽象方法无法正确获取参数名)
*/
private static String[] getMethodParamNames(final Method method) throws NotFoundException {
final String methodName = method.getName();
final Class<?>[] methodParameterTypes = method.getParameterTypes();
final int methodParameterCount = methodParameterTypes.length;
final String className = method.getDeclaringClass().getName();
final boolean isStatic = Modifier.isStatic(method.getModifiers());
final String[] methodParametersNames = new String[methodParameterCount];
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get(className);
CtClass[] ctTypes = new CtClass[methodParameterTypes.length];
for (int i = 0; i < methodParameterCount; i++) {
ctTypes[i] = pool.get(methodParameterTypes[i].getName());
}
CtMethod ctMethod = ctClass.getDeclaredMethod(methodName, ctTypes);
MethodInfo methodInfo = ctMethod.getMethodInfo();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attribute = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
// 如果是静态方法,第一个参数就是方法参数,非静态方法,则第一个参数是 this ,然后才是方法的参数
if (attribute != null) {
int variableCount = isStatic ? methodParameterCount : methodParameterCount + 1;
for (int index = 0; index < variableCount; index++) {
int methodParameterIndex = isStatic ? index : index - 1;
if (0 <= methodParameterIndex && methodParameterIndex < methodParameterCount) {
methodParametersNames[methodParameterIndex] = attribute.variableName(index);
}
}
}
return methodParametersNames;
}
Aggregations