use of javassist.bytecode.BadBytecode 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.BadBytecode 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);
}
}
}
use of javassist.bytecode.BadBytecode 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.BadBytecode 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.BadBytecode 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