use of javassist.bytecode.Bytecode 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.Bytecode 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.Bytecode in project fakereplace by fakereplace.
the class WeldClassTransformer 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 {
// Hack up the proxy factory so it stores the proxy ClassFile. We need this to regenerate proxies.
if (file.getName().equals(ORG_JBOSS_WELD_BEAN_PROXY_PROXY_FACTORY)) {
for (final MethodInfo method : (List<MethodInfo>) file.getMethods()) {
if (method.getName().equals("createProxyClass")) {
modifiedMethods.add(method);
final VirtualToStaticManipulator virtualToStaticManipulator = new VirtualToStaticManipulator();
virtualToStaticManipulator.replaceVirtualMethodInvokationWithStatic(ClassLoader.class.getName(), WELD_PROXY_CLASS_LOADING_DELEGATE, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;", loader);
virtualToStaticManipulator.replaceVirtualMethodInvokationWithStatic("org.jboss.weld.util.bytecode.ClassFileUtils", WELD_PROXY_CLASS_LOADING_DELEGATE, "toClass", "(Lorg/jboss/classfilewriter/ClassFile;Ljava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;", "(Lorg/jboss/classfilewriter/ClassFile;Ljava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;", loader);
virtualToStaticManipulator.transformClass(file, loader, true, modifiedMethods);
return true;
} else if (method.getName().equals("<init>")) {
modifiedMethods.add(method);
Integer beanArgument = null;
int count = 1;
for (final String paramType : DescriptorUtils.descriptorStringToParameterArray(method.getDescriptor())) {
if (paramType.equals("Ljavax/enterprise/inject/spi/Bean")) {
beanArgument = count;
break;
} else if (paramType.equals("D") || paramType.equals("J")) {
count += 2;
} else {
count++;
}
}
if (beanArgument == null) {
log.error("Constructor org.jboss.weld.bean.proxy.ProxyFactory.<init>" + method.getDescriptor() + " does not have a bean parameter, proxies produced by this factory will not be reloadable");
continue;
}
// similar to other tracked instances
// but we need a strong ref
Bytecode code = new Bytecode(file.getConstPool());
code.addAload(0);
code.addAload(beanArgument);
code.addInvokestatic(WeldClassChangeAware.class.getName(), "addProxyFactory", "(Ljava/lang/Object;Ljava/lang/Object;)V");
CodeIterator it = method.getCodeAttribute().iterator();
it.skipConstructor();
it.insert(code.get());
}
}
}
return false;
}
use of javassist.bytecode.Bytecode 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.Bytecode in project fakereplace by fakereplace.
the class MethodReplacementTransformer method generateFakeConstructorBytecode.
/**
* creates a class with a fake constructor that can be used by the reflection
* api
* <p>
* Constructors are not invoked through the proxy class, instead we have to
* do a lot more bytecode re-writing at the actual invocation sites
*/
private static String generateFakeConstructorBytecode(MethodInfo mInfo, ClassLoader loader) throws BadBytecode {
String proxyName = ProxyDefinitionStore.getProxyName();
ClassFile proxy = new ClassFile(false, proxyName, "java.lang.Object");
proxy.setVersionToJava5();
proxy.setAccessFlags(AccessFlag.PUBLIC);
// add our new annotations directly onto the new proxy method. This way
// they will just work without registering them with the
// AnnotationDataStore
String[] types = DescriptorUtils.descriptorStringToParameterArray(mInfo.getDescriptor());
// as this method is never called the bytecode just returns
Bytecode b = new Bytecode(proxy.getConstPool());
b.add(Opcode.ALOAD_0);
b.addInvokespecial("java.lang.Object", "<init>", "()V");
b.add(Opcode.RETURN);
MethodInfo method = new MethodInfo(proxy.getConstPool(), mInfo.getName(), mInfo.getDescriptor());
method.setAccessFlags(mInfo.getAccessFlags());
method.setCodeAttribute(b.toCodeAttribute());
method.getCodeAttribute().computeMaxStack();
method.getCodeAttribute().setMaxLocals(types.length + 1);
copyMethodAttributes(mInfo, method);
try {
proxy.addMethod(method);
} catch (DuplicateMemberException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bytes);
proxy.write(dos);
ProxyDefinitionStore.saveProxyDefinition(loader, proxyName, bytes.toByteArray());
return proxyName;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Aggregations