use of javassist.bytecode.ClassFile in project fakereplace by fakereplace.
the class MethodReplacementTransformer method generateProxyInvocationBytecode.
private static String generateProxyInvocationBytecode(MethodInfo mInfo, int methodNumber, String className, ClassLoader loader, boolean staticMethod, boolean isInterface) throws BadBytecode {
String proxyName = ProxyDefinitionStore.getProxyName();
ClassFile proxy = new ClassFile(false, proxyName, "java.lang.Object");
proxy.setVersionToJava5();
proxy.setAccessFlags(AccessFlag.PUBLIC);
// now generate our proxy that is used to actually call the method
// we use a proxy because it makes the re-writing of loaded classes
// much simpler
MethodInfo nInfo;
if (staticMethod) {
nInfo = new MethodInfo(proxy.getConstPool(), mInfo.getName(), mInfo.getDescriptor());
} else {
// the descriptor is different as now there is an extra parameter for a
// static call
String nDesc = "(" + DescriptorUtils.extToInt(className) + mInfo.getDescriptor().substring(1);
nInfo = new MethodInfo(proxy.getConstPool(), mInfo.getName(), nDesc);
}
copyMethodAttributes(mInfo, nInfo);
// set the sync bit on the proxy if it was set on the method
nInfo.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC);
Bytecode proxyBytecode = new Bytecode(proxy.getConstPool());
int paramOffset = 0;
// onto the stack
if (!staticMethod) {
proxyBytecode.addAload(0);
paramOffset = 1;
}
// stick the method number in the const pool then load it onto the
// stack
int scind = proxy.getConstPool().addIntegerInfo(methodNumber);
proxyBytecode.addLdc(scind);
String[] types = DescriptorUtils.descriptorStringToParameterArray(mInfo.getDescriptor());
// create a new array the same size as the parameter array
int index = proxyBytecode.getConstPool().addIntegerInfo(types.length);
proxyBytecode.addLdc(index);
// create new array to use to pass our parameters
proxyBytecode.addAnewarray("java.lang.Object");
int locals = types.length + paramOffset;
for (int i = 0; i < types.length; ++i) {
// duplicate the array reference on the stack
proxyBytecode.add(Opcode.DUP);
// load the array index into the stack
index = proxyBytecode.getConstPool().addIntegerInfo(i);
proxyBytecode.addLdc(index);
char tp = types[i].charAt(0);
if (tp != 'L' && tp != '[') {
// we have a primitive type
switch(tp) {
case 'J':
proxyBytecode.addLload(i + paramOffset);
locals++;
break;
case 'D':
proxyBytecode.addDload(i + paramOffset);
locals++;
break;
case 'F':
proxyBytecode.addFload(i + paramOffset);
break;
default:
proxyBytecode.addIload(i + paramOffset);
}
// lets box it
Boxing.box(proxyBytecode, tp);
} else {
// load parameter i onto
proxyBytecode.addAload(i + paramOffset);
// the stack
}
// store the value in the array
proxyBytecode.add(Opcode.AASTORE);
}
// invoke the added static method
if (staticMethod) {
proxyBytecode.addInvokestatic(className, Constants.ADDED_STATIC_METHOD_NAME, "(I[Ljava/lang/Object;)Ljava/lang/Object;");
} else if (isInterface) {
proxyBytecode.addInvokeinterface(className, Constants.ADDED_METHOD_NAME, "(I[Ljava/lang/Object;)Ljava/lang/Object;", 3);
} else {
proxyBytecode.addInvokevirtual(className, Constants.ADDED_METHOD_NAME, "(I[Ljava/lang/Object;)Ljava/lang/Object;");
}
// cast it to the appropriate type and return it
ManipulationUtils.MethodReturnRewriter.addReturnProxyMethod(mInfo.getDescriptor(), proxyBytecode);
CodeAttribute ca = proxyBytecode.toCodeAttribute();
ca.setMaxLocals(locals);
ca.computeMaxStack();
nInfo.setCodeAttribute(ca);
// this is so that we do not need to instrument the reflection API to much
if (!staticMethod) {
// as this method is never called the bytecode just returns
MethodInfo method = new MethodInfo(proxy.getConstPool(), mInfo.getName(), mInfo.getDescriptor());
method.setAccessFlags(mInfo.getAccessFlags());
if ((method.getAccessFlags() & AccessFlag.ABSTRACT) == 0) {
Bytecode b = new Bytecode(proxy.getConstPool());
String ret = DescriptorUtils.getReturnType(mInfo.getDescriptor());
if (ret.length() == 1) {
switch(ret) {
case "V":
b.add(Opcode.RETURN);
break;
case "D":
b.add(Opcode.DCONST_0);
b.add(Opcode.DRETURN);
break;
case "F":
b.add(Opcode.FCONST_0);
b.add(Opcode.FRETURN);
break;
case "J":
b.add(Opcode.LCONST_0);
b.add(Opcode.LRETURN);
break;
default:
b.add(Opcode.ICONST_0);
b.add(Opcode.IRETURN);
break;
}
} else {
b.add(Opcode.ACONST_NULL);
b.add(Opcode.ARETURN);
}
method.setCodeAttribute(b.toCodeAttribute());
method.getCodeAttribute().computeMaxStack();
method.getCodeAttribute().setMaxLocals(locals);
}
copyMethodAttributes(mInfo, method);
try {
proxy.addMethod(method);
} catch (DuplicateMemberException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
proxy.addMethod(nInfo);
} 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);
}
}
use of javassist.bytecode.ClassFile in project fakereplace by fakereplace.
the class Fakereplace method redefine.
public static void redefine(ClassDefinition[] classes, AddedClass[] addedData, boolean wait) {
try {
for (AddedClass i : addedData) {
ClassFile cf = new ClassFile(new DataInputStream(new ByteArrayInputStream(i.getData())));
mainTransformer.addNewClass(new NewClassData(i.getClassName(), i.getLoader(), cf));
}
for (ClassDefinition i : classes) {
ClassDataStore.instance().markClassReplaced(i.getDefinitionClass());
BaseClassData baseClassData = ClassDataStore.instance().getBaseClassData(i.getDefinitionClass().getClassLoader(), i.getDefinitionClass().getName());
if (baseClassData != null) {
ClassDataStore.instance().saveClassData(i.getDefinitionClass().getClassLoader(), i.getDefinitionClass().getName(), new ClassDataBuilder(baseClassData));
}
}
for (AddedClass c : addedData) {
ClassLookupManager.addClassInfo(c.getClassName(), c.getLoader(), c.getData());
}
inst.redefineClasses(classes);
clearJvmCaches();
if (wait) {
mainTransformer.waitForTasks();
}
} catch (Throwable e) {
try {
// dump the classes to /tmp so we can look at them
for (ClassDefinition d : classes) {
try {
ByteArrayInputStream bin = new ByteArrayInputStream(d.getDefinitionClassFile());
DataInputStream dis = new DataInputStream(bin);
final ClassFile file = new ClassFile(dis);
Transformer.getManipulator().transformClass(file, d.getDefinitionClass().getClassLoader(), true, new HashSet<>());
String dumpDir = AgentOptions.getOption(AgentOption.DUMP_DIR);
if (dumpDir != null) {
FileOutputStream s = new FileOutputStream(dumpDir + '/' + d.getDefinitionClass().getName() + "1.class");
DataOutputStream dos = new DataOutputStream(s);
file.write(dos);
dos.flush();
dos.close();
// s.write(d.getDefinitionClassFile());
s.close();
}
} catch (IOException a) {
a.printStackTrace();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
throw (new RuntimeException(e));
}
}
use of javassist.bytecode.ClassFile in project compss by bsc-wdc.
the class AddOrchestration method main.
public static void main(String[] args) throws NotFoundException, NameNotFoundException, CannotCompileException, IOException {
if (args.length < 2) {
ErrorManager.fatal("Error: missing arguments for loader");
}
String className = args[0];
String classPackage = getPackage(className);
// Pool creation
ClassPool pool = ClassPool.getDefault();
if (classPackage != null && classPackage.trim().length() > 0) {
pool.importPackage(classPackage);
}
// Extracting the class
CtClass cc = pool.getCtClass(className);
ClassFile ccFile = cc.getClassFile();
ConstPool constpool = ccFile.getConstPool();
for (int i = 1; i < args.length; i++) {
String methodLabel = args[i];
String methodName = getMethodName(methodLabel);
CtClass[] params = getParamClasses(methodLabel, pool);
CtMethod methodDescriptor = cc.getDeclaredMethod(methodName, params);
AnnotationsAttribute attr = (AnnotationsAttribute) methodDescriptor.getMethodInfo().getAttribute(AnnotationsAttribute.visibleTag);
if (attr == null) {
// Create the annotation
attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
}
Annotation annot = new Annotation(LoaderConstants.CLASS_ANNOTATIONS_ORCHESTRATION, constpool);
attr.addAnnotation(annot);
methodDescriptor.getMethodInfo().addAttribute(attr);
}
cc.writeFile();
// transform the ctClass to java class
/*
* Class<?> dynamiqueBeanClass = cc.toClass();
*
* //instanciating the updated class AddOrchestration ao = (AddOrchestration) dynamiqueBeanClass.newInstance();
*
* try{ Method fooMethod = ao.getClass().getDeclaredMethod(methodName, new Class<?>[] { int.class }); //getting
* the annotation Orchestration o = (Orchestration) fooMethod.getAnnotation(Orchestration.class);
* System.out.println("METHOD: " + fooMethod); System.out.println("ANNOTATION: " + o); } catch(Exception e){
* e.printStackTrace(); }
*/
}
use of javassist.bytecode.ClassFile in project tutorials by eugenp.
the class JavasisstUnitTest method givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile.
@Test
public void givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile() throws CannotCompileException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
// given
String classNameWithPackage = "com.baeldung.JavassistGeneratedClass";
ClassFile cf = new ClassFile(false, classNameWithPackage, null);
cf.setInterfaces(new String[] { "java.lang.Cloneable" });
FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I");
f.setAccessFlags(AccessFlag.PUBLIC);
cf.addField(f);
// when
String className = "JavassistGeneratedClass.class";
cf.write(new DataOutputStream(new FileOutputStream(className)));
// then
ClassPool classPool = ClassPool.getDefault();
Field[] fields = classPool.makeClass(cf).toClass().getFields();
assertEquals(fields[0].getName(), "id");
String classContent = new String(Files.readAllBytes(Paths.get(className)));
assertTrue(classContent.contains("java/lang/Cloneable"));
}
use of javassist.bytecode.ClassFile in project tutorials by eugenp.
the class JavasisstUnitTest method givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass.
@Test
public void givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass() throws NotFoundException, CannotCompileException, BadBytecode {
// given
ClassPool cp = ClassPool.getDefault();
ClassFile cf = cp.get("com.baeldung.javasisst.Point").getClassFile();
MethodInfo minfo = cf.getMethod("move");
CodeAttribute ca = minfo.getCodeAttribute();
CodeIterator ci = ca.iterator();
// when
List<String> operations = new LinkedList<>();
while (ci.hasNext()) {
int index = ci.next();
int op = ci.byteAt(index);
operations.add(Mnemonic.OPCODE[op]);
}
// then
assertEquals(operations, Arrays.asList("aload_0", "iload_1", "putfield", "aload_0", "iload_2", "putfield", "return"));
}
Aggregations