Search in sources :

Example 36 with ClassFile

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();
}
Also used : ClassFile(javassist.bytecode.ClassFile) ByteArrayInputStream(java.io.ByteArrayInputStream) CodeIterator(javassist.bytecode.CodeIterator) DataOutputStream(java.io.DataOutputStream) MethodInfo(javassist.bytecode.MethodInfo) ByteArrayOutputStream(java.io.ByteArrayOutputStream) DataInputStream(java.io.DataInputStream)

Example 37 with ClassFile

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);
    }
}
Also used : AttributeInfo(javassist.bytecode.AttributeInfo) ClassFile(javassist.bytecode.ClassFile) DataOutputStream(java.io.DataOutputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException)

Example 38 with ClassFile

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);
    }
}
Also used : AttributeInfo(javassist.bytecode.AttributeInfo) ClassFile(javassist.bytecode.ClassFile) DataOutputStream(java.io.DataOutputStream) MethodInfo(javassist.bytecode.MethodInfo) Bytecode(javassist.bytecode.Bytecode) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) IOException(java.io.IOException)

Example 39 with ClassFile

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);
    }
}
Also used : DataOutputStream(java.io.DataOutputStream) ClassPool(javassist.ClassPool) NotFoundException(javassist.NotFoundException) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode) HashSet(java.util.HashSet) ClassFile(javassist.bytecode.ClassFile) UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) ChangedClassImpl(org.fakereplace.replacement.notification.ChangedClassImpl) LoaderClassPath(javassist.LoaderClassPath) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) BadBytecode(javassist.bytecode.BadBytecode) NotFoundException(javassist.NotFoundException) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) IOException(java.io.IOException) UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) ByteArrayInputStream(java.io.ByteArrayInputStream) FileOutputStream(java.io.FileOutputStream) ChangedClass(org.fakereplace.api.ChangedClass) MethodInfo(javassist.bytecode.MethodInfo) ClassFile(javassist.bytecode.ClassFile) File(java.io.File)

Example 40 with ClassFile

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"));
}
Also used : ClassFile(javassist.bytecode.ClassFile) CodeIterator(javassist.bytecode.CodeIterator) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode) MethodInfo(javassist.bytecode.MethodInfo) LinkedList(java.util.LinkedList) Test(org.junit.Test)

Aggregations

ClassFile (javassist.bytecode.ClassFile)51 DataInputStream (java.io.DataInputStream)15 ClassPool (javassist.ClassPool)15 DataOutputStream (java.io.DataOutputStream)14 CtClass (javassist.CtClass)14 AnnotationsAttribute (javassist.bytecode.AnnotationsAttribute)14 ConstPool (javassist.bytecode.ConstPool)13 ByteArrayOutputStream (java.io.ByteArrayOutputStream)12 ByteArrayInputStream (java.io.ByteArrayInputStream)11 IOException (java.io.IOException)11 MethodInfo (javassist.bytecode.MethodInfo)11 CtField (javassist.CtField)10 NotFoundException (javassist.NotFoundException)9 Annotation (javassist.bytecode.annotation.Annotation)9 Test (org.junit.Test)9 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)8 HashSet (java.util.HashSet)7 CtMethod (javassist.CtMethod)7 FieldInfo (javassist.bytecode.FieldInfo)7 Bytecode (javassist.bytecode.Bytecode)5