use of javassist.bytecode.CodeAttribute in project pinpoint by naver.
the class JavaAssistUtils method lookupLocalVariableAttribute.
/**
* get LocalVariableAttribute
*
* @param method
* @return null if the class is not compiled with debug option
*/
public static LocalVariableAttribute lookupLocalVariableAttribute(CtBehavior method) {
if (method == null) {
throw new NullPointerException("method must not be null");
}
MethodInfo methodInfo = method.getMethodInfo2();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
if (codeAttribute == null) {
return null;
}
AttributeInfo localVariableTable = codeAttribute.getAttribute(LocalVariableAttribute.tag);
LocalVariableAttribute local = (LocalVariableAttribute) localVariableTable;
return local;
}
use of javassist.bytecode.CodeAttribute in project hibernate-orm by hibernate.
the class BulkAccessorFactory method addSetter.
private void addSetter(ClassFile classfile, final Method[] setters) throws CannotCompileException {
final ConstPool constPool = classfile.getConstPool();
final int targetTypeConstPoolIndex = constPool.addClassInfo(this.targetBean.getName());
final String desc = GET_SETTER_DESC;
final MethodInfo setterMethodInfo = new MethodInfo(constPool, GENERATED_SETTER_NAME, desc);
final Bytecode code = new Bytecode(constPool, 4, 6);
StackMapTable stackmap = null;
/* | this | bean | args | i | raw bean | exception | */
if (setters.length > 0) {
// required to exception table
int start;
int end;
// iconst_0 // i
code.addIconst(0);
// istore_3 // store i
code.addIstore(3);
// aload_1 // load the bean
code.addAload(1);
// checkcast // cast the bean into a raw bean
code.addCheckcast(this.targetBean.getName());
// astore 4 // store the raw bean
code.addAstore(4);
/* current stack len = 0 */
// start region to handling exception (BulkAccessorException)
start = code.currentPc();
int lastIndex = 0;
for (int i = 0; i < setters.length; ++i) {
if (setters[i] != null) {
final int diff = i - lastIndex;
if (diff > 0) {
// iinc 3, 1
code.addOpcode(Opcode.IINC);
code.add(3);
code.add(diff);
lastIndex = i;
}
}
/* current stack len = 0 */
// aload 4 // load the raw bean
code.addAload(4);
// aload_2 // load the args
code.addAload(2);
// iconst_i
code.addIconst(i);
// aaload
code.addOpcode(Opcode.AALOAD);
// checkcast
final Class[] setterParamTypes = setters[i].getParameterTypes();
final Class setterParamType = setterParamTypes[0];
if (setterParamType.isPrimitive()) {
// checkcast (case of primitive type)
// invokevirtual (case of primitive type)
this.addUnwrapper(code, setterParamType);
} else {
// checkcast (case of reference type)
code.addCheckcast(setterParamType.getName());
}
/* current stack len = 2 */
final String rawSetterMethodDesc = RuntimeSupport.makeDescriptor(setters[i]);
if (!this.targetBean.isInterface()) {
// invokevirtual
code.addInvokevirtual(targetTypeConstPoolIndex, setters[i].getName(), rawSetterMethodDesc);
} else {
// invokeinterface
final Class[] params = setters[i].getParameterTypes();
int size;
if (params[0].equals(Double.TYPE) || params[0].equals(Long.TYPE)) {
size = 3;
} else {
size = 2;
}
code.addInvokeinterface(targetTypeConstPoolIndex, setters[i].getName(), rawSetterMethodDesc, size);
}
}
// end region to handling exception (BulkAccessorException)
end = code.currentPc();
// return
code.addOpcode(Opcode.RETURN);
/* current stack len = 0 */
// register in exception table
final int throwableTypeIndex = constPool.addClassInfo(THROWABLE_CLASS_NAME);
final int handlerPc = code.currentPc();
code.addExceptionHandler(start, end, handlerPc, throwableTypeIndex);
// astore 5 // store exception
code.addAstore(5);
// new // BulkAccessorException
code.addNew(BULKEXCEPTION_CLASS_NAME);
// dup
code.addOpcode(Opcode.DUP);
// aload 5 // load exception
code.addAload(5);
// iload_3 // i
code.addIload(3);
// invokespecial // BulkAccessorException.<init>
final String consDesc = "(Ljava/lang/Throwable;I)V";
code.addInvokespecial(BULKEXCEPTION_CLASS_NAME, MethodInfo.nameInit, consDesc);
// athrow
code.addOpcode(Opcode.ATHROW);
final StackMapTable.Writer writer = new StackMapTable.Writer(32);
final int[] localTags = { StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.INTEGER };
final int[] localData = { constPool.getThisClassInfo(), constPool.addClassInfo("java/lang/Object"), constPool.addClassInfo("[Ljava/lang/Object;"), 0 };
final int[] stackTags = { StackMapTable.OBJECT };
final int[] stackData = { throwableTypeIndex };
writer.fullFrame(handlerPc, localTags, localData, stackTags, stackData);
stackmap = writer.toStackMapTable(constPool);
} else {
// return
code.addOpcode(Opcode.RETURN);
}
final CodeAttribute ca = code.toCodeAttribute();
if (stackmap != null) {
ca.setAttribute(stackmap);
}
setterMethodInfo.setCodeAttribute(ca);
setterMethodInfo.setAccessFlags(AccessFlag.PUBLIC);
classfile.addMethod(setterMethodInfo);
}
use of javassist.bytecode.CodeAttribute in project latke by b3log.
the class Reflections method getMethodVariableNames.
/**
* getMethodVariableNames in user defined.
*
* @param clazz the specific clazz
* @param targetMethodName the targetMethodName
* @param types the types of the method parameters
* @return the String[] of names
*/
public static String[] getMethodVariableNames(final Class<?> clazz, final String targetMethodName, final Class<?>[] types) {
CtClass cc;
CtMethod cm = null;
try {
if (null == CLASS_POOL.find(clazz.getName())) {
CLASS_POOL.insertClassPath(new ClassClassPath(clazz));
}
cc = CLASS_POOL.get(clazz.getName());
final CtClass[] ptypes = new CtClass[types.length];
for (int i = 0; i < ptypes.length; i++) {
ptypes[i] = CLASS_POOL.get(types[i].getName());
}
cm = cc.getDeclaredMethod(targetMethodName, ptypes);
} catch (final NotFoundException e) {
LOGGER.log(Level.ERROR, "Get method variable names failed", e);
}
if (null == cm) {
return new String[types.length];
}
final MethodInfo methodInfo = cm.getMethodInfo();
final CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
final LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
String[] variableNames = new String[0];
try {
variableNames = new String[cm.getParameterTypes().length];
} catch (final NotFoundException e) {
LOGGER.log(Level.ERROR, "Get method variable names failed", e);
}
// final int staticIndex = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
int j = -1;
String variableName = null;
Boolean ifkill = false;
while (!"this".equals(variableName)) {
j++;
variableName = attr.variableName(j);
// to prevent heap error when there being some unknown reasons to resolve the VariableNames
if (j > MAX_FIND_LENGTH) {
LOGGER.log(Level.WARN, "Maybe resolve to VariableNames error [class=" + clazz.getName() + ", targetMethodName=" + targetMethodName + ']');
ifkill = true;
break;
}
}
if (!ifkill) {
for (int i = 0; i < variableNames.length; i++) {
variableNames[i] = attr.variableName(++j);
}
}
return variableNames;
}
use of javassist.bytecode.CodeAttribute in project fakereplace by fakereplace.
the class WildflyClassTransformer method transform.
@Override
public boolean transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, ClassFile file, Set<Class<?>> classesToRetransform, ChangedClassImpl changedClass, Set<MethodInfo> modifiedMethods) throws IllegalClassFormatException, BadBytecode, DuplicateMemberException {
if (!file.getName().equals("org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService")) {
return false;
}
for (MethodInfo method : (List<MethodInfo>) file.getMethods()) {
if (method.getName().equals("createServletConfig")) {
CodeAttribute code = method.getCodeAttribute();
code.setMaxStack(code.getMaxStack() + 1);
CodeIterator it = code.iterator();
modifiedMethods.add(method);
while (it.hasNext()) {
int pos = it.next();
int inst = it.byteAt(pos);
if (inst == CodeAttribute.ARETURN) {
Bytecode b = new Bytecode(method.getConstPool());
b.addGetstatic("org.fakereplace.integration.wildfly.autoupdate.WebUpdateHandlerWrapper", "INSTANCE", "Lio/undertow/server/HandlerWrapper;");
b.addInvokevirtual("io.undertow.servlet.api.DeploymentInfo", "addInnerHandlerChainWrapper", "(Lio/undertow/server/HandlerWrapper;)Lio/undertow/servlet/api/DeploymentInfo;");
it.insert(pos, b.get());
}
}
}
}
return true;
}
use of javassist.bytecode.CodeAttribute in project fakereplace by fakereplace.
the class MethodReplacementTransformer method transform.
@Override
public boolean transform(ClassLoader loader, String className, Class<?> oldClass, ProtectionDomain protectionDomain, ClassFile file, Set<Class<?>> classesToRetransform, ChangedClassImpl changedClass, Set<MethodInfo> modifiedMethods) throws IllegalClassFormatException, BadBytecode, DuplicateMemberException {
if (oldClass == null || className == null) {
return false;
}
final Set<MethodData> methodsToRemove = new HashSet<>();
final Set<FakeMethod> methodsToAdd = new HashSet<>();
final Set<FakeMethod> constructorsToAdd = new HashSet<>();
BaseClassData data = ClassDataStore.instance().getBaseClassData(loader, className);
// state for added static methods
CodeAttribute staticCodeAttribute = null, virtualCodeAttribute = null, constructorCodeAttribute = null;
try {
// stick our added methods into the class file
// we can't finalise the code yet because we will probably need
// the add stuff to them
MethodInfo virtMethod = new MethodInfo(file.getConstPool(), Constants.ADDED_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
modifiedMethods.add(virtMethod);
virtMethod.setAccessFlags(AccessFlag.PUBLIC);
if (file.isInterface()) {
virtMethod.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.ABSTRACT | AccessFlag.SYNTHETIC);
} else {
virtMethod.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.SYNTHETIC);
Bytecode b = new Bytecode(file.getConstPool(), 0, 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 {
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);
}
virtualCodeAttribute = b.toCodeAttribute();
virtMethod.setCodeAttribute(virtualCodeAttribute);
MethodInfo m = new MethodInfo(file.getConstPool(), Constants.ADDED_STATIC_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
modifiedMethods.add(m);
m.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC | AccessFlag.SYNTHETIC);
b = new Bytecode(file.getConstPool(), 0, 3);
b.addNew(NoSuchMethodError.class.getName());
b.add(Opcode.DUP);
b.addInvokespecial(NoSuchMethodError.class.getName(), "<init>", "()V");
b.add(Opcode.ATHROW);
staticCodeAttribute = b.toCodeAttribute();
m.setCodeAttribute(staticCodeAttribute);
file.addMethod(m);
m = new MethodInfo(file.getConstPool(), "<init>", Constants.ADDED_CONSTRUCTOR_DESCRIPTOR);
modifiedMethods.add(m);
m.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.SYNTHETIC);
b = new Bytecode(file.getConstPool(), 0, 4);
if (ManipulationUtils.addBogusConstructorCall(file, b)) {
constructorCodeAttribute = b.toCodeAttribute();
m.setCodeAttribute(constructorCodeAttribute);
constructorCodeAttribute.setMaxLocals(6);
file.addMethod(m);
}
}
file.addMethod(virtMethod);
} catch (DuplicateMemberException e) {
e.printStackTrace();
}
Set<MethodData> methods = new HashSet<>();
methods.addAll(data.getMethods());
ListIterator<?> it = file.getMethods().listIterator();
// IncompatibleClassChange exception will be thrown
while (it.hasNext()) {
MethodInfo m = (MethodInfo) it.next();
MethodData md = null;
boolean upgradedVisibility = false;
for (MethodData i : methods) {
if (i.getMethodName().equals(m.getName()) && i.getDescriptor().equals(m.getDescriptor())) {
// depends on what has changed
if (i.getAccessFlags() != m.getAccessFlags()) {
if (AccessFlagUtils.upgradeVisibility(m.getAccessFlags(), i.getAccessFlags())) {
upgradedVisibility = true;
} else if (AccessFlagUtils.downgradeVisibility(m.getAccessFlags(), i.getAccessFlags())) {
// ignore this, we don't need to do anything
} else {
// we can't handle this yet
continue;
}
}
m.setAccessFlags(i.getAccessFlags());
// if it is the constructor
if (m.getName().equals("<init>")) {
try {
Constructor<?> meth = i.getConstructor(oldClass);
AnnotationDataStore.recordConstructorAnnotations(meth, (AnnotationsAttribute) m.getAttribute(AnnotationsAttribute.visibleTag));
AnnotationDataStore.recordConstructorParameterAnnotations(meth, (ParameterAnnotationsAttribute) m.getAttribute(ParameterAnnotationsAttribute.visibleTag));
// now revert the annotations:
m.addAttribute(AnnotationReplacer.duplicateAnnotationsAttribute(file.getConstPool(), meth));
m.addAttribute(AnnotationReplacer.duplicateParameterAnnotationsAttribute(file.getConstPool(), meth));
} catch (Exception e) {
throw new RuntimeException(e);
}
} else if (!m.getName().equals("<clinit>")) {
// we do not have to worry about them
try {
Method meth = i.getMethod(oldClass);
AnnotationDataStore.recordMethodAnnotations(meth, (AnnotationsAttribute) m.getAttribute(AnnotationsAttribute.visibleTag));
AnnotationDataStore.recordMethodParameterAnnotations(meth, (ParameterAnnotationsAttribute) m.getAttribute(ParameterAnnotationsAttribute.visibleTag));
// now revert the annotations:
m.addAttribute(AnnotationReplacer.duplicateAnnotationsAttribute(file.getConstPool(), meth));
m.addAttribute(AnnotationReplacer.duplicateParameterAnnotationsAttribute(file.getConstPool(), meth));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
md = i;
break;
}
}
// we do not need to deal with these
if (m.getName().equals(Constants.ADDED_METHOD_NAME) || m.getName().equals(Constants.ADDED_STATIC_METHOD_NAME)) {
break;
}
// so it is still in the original
if (md == null || upgradedVisibility) {
if ((m.getAccessFlags() & AccessFlag.STATIC) != 0) {
Class<?> c = addMethod(file, loader, m, methodsToAdd, staticCodeAttribute, true, oldClass);
if (c != null) {
classesToRetransform.add(c);
}
} else if ((m.getName().equals("<init>"))) {
addConstructor(file, loader, m, constructorsToAdd, constructorCodeAttribute, oldClass);
} else if (m.getName().equals("<clinit>")) {
// nop, we can't change this, just ignore it
} else {
Class<?> c = addMethod(file, loader, m, methodsToAdd, virtualCodeAttribute, false, oldClass);
if (c != null) {
classesToRetransform.add(c);
}
}
if (!upgradedVisibility) {
it.remove();
}
} else {
methods.remove(md);
}
if (upgradedVisibility) {
methods.remove(md);
}
}
for (MethodData md : methods) {
if (md.getType() == MemberType.NORMAL) {
MethodInfo removedMethod = createRemovedMethod(file, md, oldClass, methodsToRemove);
if (removedMethod != null) {
modifiedMethods.add(removedMethod);
}
}
}
ClassDataStore.instance().modifyCurrentData(loader, className, (builder) -> {
for (MethodData method : methodsToRemove) {
builder.removeMethod(method);
}
for (FakeMethod fake : methodsToAdd) {
ClassDataStore.instance().registerReplacedMethod(fake.proxyName, builder.addFakeMethod(fake.name, fake.descriptor, fake.proxyName, fake.accessFlags));
}
for (FakeMethod fake : constructorsToAdd) {
ClassDataStore.instance().registerReplacedMethod(fake.proxyName, builder.addFakeConstructor(fake.name, fake.descriptor, fake.proxyName, fake.accessFlags, fake.methodCount));
}
});
// the method declaration to propagate the call to the parent
if (!file.isInterface()) {
try {
staticCodeAttribute.computeMaxStack();
virtualCodeAttribute.computeMaxStack();
if (constructorCodeAttribute != null) {
constructorCodeAttribute.computeMaxStack();
}
} catch (BadBytecode e) {
e.printStackTrace();
}
}
return true;
}
Aggregations