use of javassist.bytecode.MethodInfo 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.MethodInfo in project hibernate-orm by hibernate.
the class BulkAccessorFactory method addGetter.
private void addGetter(ClassFile classfile, final Method[] getters) throws CannotCompileException {
final ConstPool constPool = classfile.getConstPool();
final int targetBeanConstPoolIndex = constPool.addClassInfo(this.targetBean.getName());
final String desc = GET_SETTER_DESC;
final MethodInfo getterMethodInfo = new MethodInfo(constPool, GENERATED_GETTER_NAME, desc);
final Bytecode code = new Bytecode(constPool, 6, 4);
/* | this | bean | args | raw bean | */
if (getters.length >= 0) {
// aload_1 // load bean
code.addAload(1);
// checkcast // cast bean
code.addCheckcast(this.targetBean.getName());
// astore_3 // store bean
code.addAstore(3);
for (int i = 0; i < getters.length; ++i) {
if (getters[i] != null) {
final Method getter = getters[i];
// aload_2 // args
code.addAload(2);
// iconst_i // continue to aastore
// growing stack is 1
code.addIconst(i);
final Class returnType = getter.getReturnType();
int typeIndex = -1;
if (returnType.isPrimitive()) {
typeIndex = FactoryHelper.typeIndex(returnType);
// new
code.addNew(FactoryHelper.wrapperTypes[typeIndex]);
// dup
code.addOpcode(Opcode.DUP);
}
// aload_3 // load the raw bean
code.addAload(3);
final String getterSignature = RuntimeSupport.makeDescriptor(getter);
final String getterName = getter.getName();
if (this.targetBean.isInterface()) {
// invokeinterface
code.addInvokeinterface(targetBeanConstPoolIndex, getterName, getterSignature, 1);
} else {
// invokevirtual
code.addInvokevirtual(targetBeanConstPoolIndex, getterName, getterSignature);
}
if (typeIndex >= 0) {
// is a primitive type
// invokespecial
code.addInvokespecial(FactoryHelper.wrapperTypes[typeIndex], MethodInfo.nameInit, FactoryHelper.wrapperDesc[typeIndex]);
}
// aastore // args
code.add(Opcode.AASTORE);
code.growStack(-3);
}
}
}
// return
code.addOpcode(Opcode.RETURN);
getterMethodInfo.setCodeAttribute(code.toCodeAttribute());
getterMethodInfo.setAccessFlags(AccessFlag.PUBLIC);
classfile.addMethod(getterMethodInfo);
}
use of javassist.bytecode.MethodInfo 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.MethodInfo in project hibernate-orm by hibernate.
the class PersistentAttributesEnhancer method enhanceAttributesAccess.
protected void enhanceAttributesAccess(CtClass managedCtClass, IdentityHashMap<String, PersistentAttributeAccessMethods> attributeDescriptorMap) {
final ConstPool constPool = managedCtClass.getClassFile().getConstPool();
final ClassPool classPool = managedCtClass.getClassPool();
for (Object oMethod : managedCtClass.getClassFile().getMethods()) {
final MethodInfo methodInfo = (MethodInfo) oMethod;
final String methodName = methodInfo.getName();
// skip methods added by enhancement and abstract methods (methods without any code)
if (methodName.startsWith("$$_hibernate_") || methodInfo.getCodeAttribute() == null) {
continue;
}
try {
final CodeIterator itr = methodInfo.getCodeAttribute().iterator();
while (itr.hasNext()) {
final int index = itr.next();
final int op = itr.byteAt(index);
if (op != Opcode.PUTFIELD && op != Opcode.GETFIELD) {
continue;
}
// only transform access to fields of the entity being enhanced
if (!managedCtClass.getName().equals(constPool.getFieldrefClassName(itr.u16bitAt(index + 1)))) {
continue;
}
final String fieldName = constPool.getFieldrefName(itr.u16bitAt(index + 1));
final PersistentAttributeAccessMethods attributeMethods = attributeDescriptorMap.get(fieldName);
// its not a field we have enhanced for interception, so skip it
if (attributeMethods == null) {
continue;
}
// System.out.printf( "Transforming access to field [%s] from method [%s]%n", fieldName, methodName );
log.debugf("Transforming access to field [%s] from method [%s]", fieldName, methodName);
if (op == Opcode.GETFIELD) {
final int methodIndex = MethodWriter.addMethod(constPool, attributeMethods.getReader());
itr.writeByte(Opcode.INVOKEVIRTUAL, index);
itr.write16bit(methodIndex, index + 1);
} else {
final int methodIndex = MethodWriter.addMethod(constPool, attributeMethods.getWriter());
itr.writeByte(Opcode.INVOKEVIRTUAL, index);
itr.write16bit(methodIndex, index + 1);
}
}
methodInfo.getCodeAttribute().setAttribute(MapMaker.make(classPool, methodInfo));
} catch (BadBytecode bb) {
final String msg = String.format("Unable to perform field access transformation in method [%s]", methodName);
throw new EnhancementException(msg, bb);
}
}
}
use of javassist.bytecode.MethodInfo in project hibernate-orm by hibernate.
the class PersistentAttributesEnhancer method extendedEnhancement.
// --- //
/**
* Replace access to fields of entities (for example, entity.field) with a call to the enhanced getter / setter
* (in this example, entity.$$_hibernate_read_field()). It's assumed that the target entity is enhanced as well.
*
* @param aCtClass Class to enhance (not an entity class).
*/
public void extendedEnhancement(CtClass aCtClass) {
final ConstPool constPool = aCtClass.getClassFile().getConstPool();
final ClassPool classPool = aCtClass.getClassPool();
for (Object oMethod : aCtClass.getClassFile().getMethods()) {
final MethodInfo methodInfo = (MethodInfo) oMethod;
final String methodName = methodInfo.getName();
// skip methods added by enhancement and abstract methods (methods without any code)
if (methodName.startsWith("$$_hibernate_") || methodInfo.getCodeAttribute() == null) {
continue;
}
try {
final CodeIterator itr = methodInfo.getCodeAttribute().iterator();
while (itr.hasNext()) {
int index = itr.next();
int op = itr.byteAt(index);
if (op != Opcode.PUTFIELD && op != Opcode.GETFIELD) {
continue;
}
String fieldName = constPool.getFieldrefName(itr.u16bitAt(index + 1));
String fieldClassName = constPool.getClassInfo(constPool.getFieldrefClass(itr.u16bitAt(index + 1)));
CtClass targetCtClass = classPool.getCtClass(fieldClassName);
if (!enhancementContext.isEntityClass(targetCtClass) && !enhancementContext.isCompositeClass(targetCtClass)) {
continue;
}
if (targetCtClass == aCtClass || !enhancementContext.isPersistentField(targetCtClass.getField(fieldName)) || PersistentAttributesHelper.hasAnnotation(targetCtClass, fieldName, Id.class) || "this$0".equals(fieldName)) {
continue;
}
log.debugf("Extended enhancement: Transforming access to field [%s.%s] from method [%s#%s]", fieldClassName, fieldName, aCtClass.getName(), methodName);
if (op == Opcode.GETFIELD) {
int fieldReaderMethodIndex = constPool.addMethodrefInfo(constPool.addClassInfo(fieldClassName), EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + fieldName, "()" + constPool.getFieldrefType(itr.u16bitAt(index + 1)));
itr.writeByte(Opcode.INVOKEVIRTUAL, index);
itr.write16bit(fieldReaderMethodIndex, index + 1);
} else {
int fieldWriterMethodIndex = constPool.addMethodrefInfo(constPool.addClassInfo(fieldClassName), EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + fieldName, "(" + constPool.getFieldrefType(itr.u16bitAt(index + 1)) + ")V");
itr.writeByte(Opcode.INVOKEVIRTUAL, index);
itr.write16bit(fieldWriterMethodIndex, index + 1);
}
}
methodInfo.getCodeAttribute().setAttribute(MapMaker.make(classPool, methodInfo));
} catch (BadBytecode bb) {
final String msg = String.format("Unable to perform extended enhancement in method [%s]", methodName);
throw new EnhancementException(msg, bb);
} catch (NotFoundException nfe) {
final String msg = String.format("Unable to perform extended enhancement in method [%s]", methodName);
throw new EnhancementException(msg, nfe);
}
}
}
Aggregations