use of javassist.bytecode.ClassFile in project openj9 by eclipse.
the class SharedInvokersTestGenerator method modifyInvokerOperand.
/*
* This method is to workaround a limitation of ASM which prevents
* generating class file where invokeinterface and invoke[static|special]
* bytecodes share same constant pool entry.
*
* To overcome this limitation, after the ASM has generated class data, the
* operand of invoke[static|special] bytecodes is modified to be same as the
* operand of invokeinterface bytecode. It uses javassist APIs to make this
* modification.
*/
public static byte[] modifyInvokerOperand(byte[] data) throws Exception {
int cpIndex = 0;
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ClassFile classFile = new ClassFile(new DataInputStream(bais));
/* Record operand of invokeinterface in sharedInvokers() */
MethodInfo methodInfo = classFile.getMethod("sharedInvokers");
CodeIterator ci = methodInfo.getCodeAttribute().iterator();
while (ci.hasNext()) {
int bcIndex = ci.next();
int bc = ci.byteAt(bcIndex);
if (bc == Opcode.INVOKEINTERFACE) {
/* found invokeinterfce bytecode */
cpIndex = ci.s16bitAt(bcIndex + 1);
break;
}
}
/*
* Modify operand of invokestatic/invokespecial to cpIndex recorded
* above
*/
ci = methodInfo.getCodeAttribute().iterator();
while (ci.hasNext()) {
int bcIndex = ci.next();
int bc = ci.byteAt(bcIndex);
if ((bc == Opcode.INVOKESPECIAL) || (bc == Opcode.INVOKESTATIC)) {
/*
* found invokespecial or invokestatic bytecode; update the
* operand constant pool index
*/
ci.write16bit(cpIndex, bcIndex + 1);
}
}
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
DataOutputStream dataStream = new DataOutputStream(byteStream);
classFile.write(dataStream);
return byteStream.toByteArray();
}
use of javassist.bytecode.ClassFile in project fakereplace by fakereplace.
the class AnnotationDataStore method createAnnotationsProxy.
private static Class<?> createAnnotationsProxy(ClassLoader loader, AnnotationsAttribute annotations) {
String proxyName = ProxyDefinitionStore.getProxyName();
ClassFile proxy = new ClassFile(false, proxyName, "java.lang.Object");
proxy.setAccessFlags(AccessFlag.PUBLIC);
AttributeInfo a = annotations.copy(proxy.getConstPool(), Collections.EMPTY_MAP);
proxy.addAttribute(a);
try {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bytes);
try {
proxy.write(dos);
} catch (IOException e) {
throw new RuntimeException(e);
}
ProxyDefinitionStore.saveProxyDefinition(loader, proxyName, bytes.toByteArray());
return loader.loadClass(proxyName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
use of javassist.bytecode.ClassFile in project fakereplace by fakereplace.
the class AnnotationDataStore method createParameterAnnotationsProxy.
private static Class<?> createParameterAnnotationsProxy(ClassLoader loader, ParameterAnnotationsAttribute annotations, int paramCount) {
String proxyName = ProxyDefinitionStore.getProxyName();
ClassFile proxy = new ClassFile(false, proxyName, "java.lang.Object");
proxy.setAccessFlags(AccessFlag.PUBLIC);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < paramCount; ++i) {
sb.append("I");
}
MethodInfo method = new MethodInfo(proxy.getConstPool(), PROXY_METHOD_NAME, "(" + sb.toString() + ")V");
Bytecode b = new Bytecode(proxy.getConstPool());
b.add(Opcode.RETURN);
method.setAccessFlags(AccessFlag.PUBLIC);
method.setCodeAttribute(b.toCodeAttribute());
method.getCodeAttribute().setMaxLocals(paramCount + 1);
AttributeInfo an = annotations.copy(proxy.getConstPool(), Collections.EMPTY_MAP);
method.addAttribute(an);
try {
proxy.addMethod(method);
method.getCodeAttribute().computeMaxStack();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bytes);
try {
proxy.write(dos);
} catch (IOException e) {
throw new RuntimeException(e);
}
ProxyDefinitionStore.saveProxyDefinition(loader, proxyName, bytes.toByteArray());
return loader.loadClass(proxyName);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of javassist.bytecode.ClassFile in project fakereplace by fakereplace.
the class MainTransformer method transform.
@Override
public byte[] transform(final ClassLoader loader, final String className, final Class<?> classBeingRedefined, final ProtectionDomain protectionDomain, final byte[] classfileBuffer) throws IllegalClassFormatException {
if (className == null) {
// TODO: deal with lambdas
return classfileBuffer;
}
boolean replaceable = Fakereplace.isClassReplaceable(className, loader);
if (classBeingRedefined != null) {
retransformationStarted = true;
if (logClassRetransformation && replaceable) {
log.info("Fakereplace is replacing class " + className);
}
}
ChangedClassImpl changedClass = null;
if (classBeingRedefined != null) {
changedClass = new ChangedClassImpl(classBeingRedefined);
}
boolean changed = false;
if (!replaceable && UnmodifiedFileIndex.isClassUnmodified(className)) {
return null;
}
Set<Class<?>> classesToRetransform = new HashSet<>();
final ClassFile file;
try {
Set<MethodInfo> modifiedMethods = new HashSet<>();
file = new ClassFile(new DataInputStream(new ByteArrayInputStream(classfileBuffer)));
for (final FakereplaceTransformer transformer : transformers) {
if (transformer.transform(loader, className, classBeingRedefined, protectionDomain, file, classesToRetransform, changedClass, modifiedMethods)) {
changed = true;
}
}
if (!changed) {
UnmodifiedFileIndex.markClassUnmodified(className);
return null;
} else {
try {
if (!modifiedMethods.isEmpty()) {
ClassPool classPool = new ClassPool();
if (loader == null) {
classPool.appendClassPath(new LoaderClassPath(ClassLoader.getSystemClassLoader()));
} else {
classPool.appendClassPath(new LoaderClassPath(loader));
}
classPool.appendSystemPath();
for (MethodInfo method : modifiedMethods) {
if (method.getCodeAttribute() != null) {
method.getCodeAttribute().computeMaxStack();
try {
method.rebuildStackMap(classPool);
} catch (BadBytecode e) {
Throwable root = e;
while (!(root instanceof NotFoundException) && root != null && root.getCause() != root) {
root = root.getCause();
}
if (root instanceof NotFoundException) {
NotFoundException cause = (NotFoundException) root;
Bytecode bytecode = new Bytecode(file.getConstPool());
bytecode.addNew(NoClassDefFoundError.class.getName());
bytecode.add(Opcode.DUP);
bytecode.addLdc(cause.getMessage());
bytecode.addInvokespecial(NoClassDefFoundError.class.getName(), "<init>", "(Ljava/lang/String;)V");
bytecode.add(Opcode.ATHROW);
method.setCodeAttribute(bytecode.toCodeAttribute());
method.getCodeAttribute().computeMaxStack();
method.getCodeAttribute().setMaxLocals(DescriptorUtils.maxLocalsFromParameters(method.getDescriptor()) + 1);
method.rebuildStackMap(classPool);
} else {
throw e;
}
}
}
}
}
} catch (BadBytecode e) {
throw new RuntimeException(e);
}
ByteArrayOutputStream bs = new ByteArrayOutputStream();
file.write(new DataOutputStream(bs));
// dump the class for debugging purposes
final String dumpDir = AgentOptions.getOption(AgentOption.DUMP_DIR);
if (dumpDir != null) {
try {
File dump = new File(dumpDir + '/' + file.getName() + ".class");
dump.getParentFile().mkdirs();
FileOutputStream s = new FileOutputStream(dump);
DataOutputStream dos = new DataOutputStream(s);
file.write(dos);
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (!classesToRetransform.isEmpty()) {
synchronized (this) {
retransformationOutstandingCount++;
}
Thread t = new Thread(() -> {
try {
Fakereplace.getInstrumentation().retransformClasses(classesToRetransform.toArray(new Class[classesToRetransform.size()]));
} catch (UnmodifiableClassException e) {
log.error("Failed to retransform classes", e);
} finally {
synchronized (MainTransformer.this) {
retransformationOutstandingCount--;
notifyAll();
}
}
});
t.setDaemon(true);
t.start();
}
if (classBeingRedefined != null) {
changedClasses.add(changedClass);
queueIntegration();
}
return bs.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
throw new IllegalClassFormatException(e.getMessage());
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
use of javassist.bytecode.ClassFile in project tutorials by eugenp.
the class JavasisstUnitTest method givenLoadedClass_whenAddConstructorToClass_shouldCreateClassWithConstructor.
@Test
public void givenLoadedClass_whenAddConstructorToClass_shouldCreateClassWithConstructor() throws NotFoundException, CannotCompileException, BadBytecode {
// given
ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.Point").getClassFile();
Bytecode code = new Bytecode(cf.getConstPool());
code.addAload(0);
code.addInvokespecial("java/lang/Object", MethodInfo.nameInit, "()V");
code.addReturn(null);
// when
MethodInfo minfo = new MethodInfo(cf.getConstPool(), MethodInfo.nameInit, "()V");
minfo.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(minfo);
// then
CodeIterator ci = code.toCodeAttribute().iterator();
List<String> operations = new LinkedList<>();
while (ci.hasNext()) {
int index = ci.next();
int op = ci.byteAt(index);
operations.add(Mnemonic.OPCODE[op]);
}
assertEquals(operations, Arrays.asList("aload_0", "invokespecial", "return"));
}
Aggregations