Search in sources :

Example 51 with CtClass

use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.

the class PluginManagerInvokerTest method testBuildCallPluginMethod.

@Test
public void testBuildCallPluginMethod() throws Exception {
    SimplePlugin plugin = new SimplePlugin();
    registerPlugin(plugin);
    // plugin.init(PluginManager.getInstance());
    String s = PluginManagerInvoker.buildCallPluginMethod(plugin.getClass(), "callPluginMethod", "Boolean.TRUE", "java.lang.Boolean");
    ClassPool classPool = ClassPool.getDefault();
    classPool.appendSystemPath();
    CtClass clazz = classPool.makeClass("Test");
    clazz.addMethod(CtNewMethod.make("public void test() {" + s + "}", clazz));
    Class<?> testClass = clazz.toClass();
    Method testMethod = testClass.getDeclaredMethod("test");
    testMethod.invoke(testClass.newInstance());
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) ClassPool(org.hotswap.agent.javassist.ClassPool) SimplePlugin(org.hotswap.agent.testData.SimplePlugin) CtNewMethod(org.hotswap.agent.javassist.CtNewMethod) Method(java.lang.reflect.Method) Test(org.junit.Test)

Example 52 with CtClass

use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.

the class Executor method execute.

/**
 * Execute the instruction, modeling the effects on the specified frame and subroutine.
 * If a subroutine is passed, the access flags will be modified if this instruction accesses
 * the local variable table.
 *
 * @param method the method containing the instruction
 * @param pos the position of the instruction in the method
 * @param iter the code iterator used to find the instruction
 * @param frame the frame to modify to represent the result of the instruction
 * @param subroutine the optional subroutine this instruction belongs to.
 * @throws BadBytecode if the bytecode violates the jvm spec
 */
public void execute(MethodInfo method, int pos, CodeIterator iter, Frame frame, Subroutine subroutine) throws BadBytecode {
    this.lastPos = pos;
    int opcode = iter.byteAt(pos);
    // Declared opcode in order
    switch(opcode) {
        case NOP:
            break;
        case ACONST_NULL:
            frame.push(Type.UNINIT);
            break;
        case ICONST_M1:
        case ICONST_0:
        case ICONST_1:
        case ICONST_2:
        case ICONST_3:
        case ICONST_4:
        case ICONST_5:
            frame.push(Type.INTEGER);
            break;
        case LCONST_0:
        case LCONST_1:
            frame.push(Type.LONG);
            frame.push(Type.TOP);
            break;
        case FCONST_0:
        case FCONST_1:
        case FCONST_2:
            frame.push(Type.FLOAT);
            break;
        case DCONST_0:
        case DCONST_1:
            frame.push(Type.DOUBLE);
            frame.push(Type.TOP);
            break;
        case BIPUSH:
        case SIPUSH:
            frame.push(Type.INTEGER);
            break;
        case LDC:
            evalLDC(iter.byteAt(pos + 1), frame);
            break;
        case LDC_W:
        case LDC2_W:
            evalLDC(iter.u16bitAt(pos + 1), frame);
            break;
        case ILOAD:
            evalLoad(Type.INTEGER, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case LLOAD:
            evalLoad(Type.LONG, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case FLOAD:
            evalLoad(Type.FLOAT, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case DLOAD:
            evalLoad(Type.DOUBLE, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case ALOAD:
            evalLoad(Type.OBJECT, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case ILOAD_0:
        case ILOAD_1:
        case ILOAD_2:
        case ILOAD_3:
            evalLoad(Type.INTEGER, opcode - ILOAD_0, frame, subroutine);
            break;
        case LLOAD_0:
        case LLOAD_1:
        case LLOAD_2:
        case LLOAD_3:
            evalLoad(Type.LONG, opcode - LLOAD_0, frame, subroutine);
            break;
        case FLOAD_0:
        case FLOAD_1:
        case FLOAD_2:
        case FLOAD_3:
            evalLoad(Type.FLOAT, opcode - FLOAD_0, frame, subroutine);
            break;
        case DLOAD_0:
        case DLOAD_1:
        case DLOAD_2:
        case DLOAD_3:
            evalLoad(Type.DOUBLE, opcode - DLOAD_0, frame, subroutine);
            break;
        case ALOAD_0:
        case ALOAD_1:
        case ALOAD_2:
        case ALOAD_3:
            evalLoad(Type.OBJECT, opcode - ALOAD_0, frame, subroutine);
            break;
        case IALOAD:
            evalArrayLoad(Type.INTEGER, frame);
            break;
        case LALOAD:
            evalArrayLoad(Type.LONG, frame);
            break;
        case FALOAD:
            evalArrayLoad(Type.FLOAT, frame);
            break;
        case DALOAD:
            evalArrayLoad(Type.DOUBLE, frame);
            break;
        case AALOAD:
            evalArrayLoad(Type.OBJECT, frame);
            break;
        case BALOAD:
        case CALOAD:
        case SALOAD:
            evalArrayLoad(Type.INTEGER, frame);
            break;
        case ISTORE:
            evalStore(Type.INTEGER, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case LSTORE:
            evalStore(Type.LONG, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case FSTORE:
            evalStore(Type.FLOAT, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case DSTORE:
            evalStore(Type.DOUBLE, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case ASTORE:
            evalStore(Type.OBJECT, iter.byteAt(pos + 1), frame, subroutine);
            break;
        case ISTORE_0:
        case ISTORE_1:
        case ISTORE_2:
        case ISTORE_3:
            evalStore(Type.INTEGER, opcode - ISTORE_0, frame, subroutine);
            break;
        case LSTORE_0:
        case LSTORE_1:
        case LSTORE_2:
        case LSTORE_3:
            evalStore(Type.LONG, opcode - LSTORE_0, frame, subroutine);
            break;
        case FSTORE_0:
        case FSTORE_1:
        case FSTORE_2:
        case FSTORE_3:
            evalStore(Type.FLOAT, opcode - FSTORE_0, frame, subroutine);
            break;
        case DSTORE_0:
        case DSTORE_1:
        case DSTORE_2:
        case DSTORE_3:
            evalStore(Type.DOUBLE, opcode - DSTORE_0, frame, subroutine);
            break;
        case ASTORE_0:
        case ASTORE_1:
        case ASTORE_2:
        case ASTORE_3:
            evalStore(Type.OBJECT, opcode - ASTORE_0, frame, subroutine);
            break;
        case IASTORE:
            evalArrayStore(Type.INTEGER, frame);
            break;
        case LASTORE:
            evalArrayStore(Type.LONG, frame);
            break;
        case FASTORE:
            evalArrayStore(Type.FLOAT, frame);
            break;
        case DASTORE:
            evalArrayStore(Type.DOUBLE, frame);
            break;
        case AASTORE:
            evalArrayStore(Type.OBJECT, frame);
            break;
        case BASTORE:
        case CASTORE:
        case SASTORE:
            evalArrayStore(Type.INTEGER, frame);
            break;
        case POP:
            if (frame.pop() == Type.TOP)
                throw new BadBytecode("POP can not be used with a category 2 value, pos = " + pos);
            break;
        case POP2:
            frame.pop();
            frame.pop();
            break;
        case DUP:
            {
                Type type = frame.peek();
                if (type == Type.TOP)
                    throw new BadBytecode("DUP can not be used with a category 2 value, pos = " + pos);
                frame.push(frame.peek());
                break;
            }
        case DUP_X1:
        case DUP_X2:
            {
                Type type = frame.peek();
                if (type == Type.TOP)
                    throw new BadBytecode("DUP can not be used with a category 2 value, pos = " + pos);
                int end = frame.getTopIndex();
                int insert = end - (opcode - DUP_X1) - 1;
                frame.push(type);
                while (end > insert) {
                    frame.setStack(end, frame.getStack(end - 1));
                    end--;
                }
                frame.setStack(insert, type);
                break;
            }
        case DUP2:
            frame.push(frame.getStack(frame.getTopIndex() - 1));
            frame.push(frame.getStack(frame.getTopIndex() - 1));
            break;
        case DUP2_X1:
        case DUP2_X2:
            {
                int end = frame.getTopIndex();
                int insert = end - (opcode - DUP2_X1) - 1;
                Type type1 = frame.getStack(frame.getTopIndex() - 1);
                Type type2 = frame.peek();
                frame.push(type1);
                frame.push(type2);
                while (end > insert) {
                    frame.setStack(end, frame.getStack(end - 2));
                    end--;
                }
                frame.setStack(insert, type2);
                frame.setStack(insert - 1, type1);
                break;
            }
        case SWAP:
            {
                Type type1 = frame.pop();
                Type type2 = frame.pop();
                if (type1.getSize() == 2 || type2.getSize() == 2)
                    throw new BadBytecode("Swap can not be used with category 2 values, pos = " + pos);
                frame.push(type1);
                frame.push(type2);
                break;
            }
        // Math
        case IADD:
            evalBinaryMath(Type.INTEGER, frame);
            break;
        case LADD:
            evalBinaryMath(Type.LONG, frame);
            break;
        case FADD:
            evalBinaryMath(Type.FLOAT, frame);
            break;
        case DADD:
            evalBinaryMath(Type.DOUBLE, frame);
            break;
        case ISUB:
            evalBinaryMath(Type.INTEGER, frame);
            break;
        case LSUB:
            evalBinaryMath(Type.LONG, frame);
            break;
        case FSUB:
            evalBinaryMath(Type.FLOAT, frame);
            break;
        case DSUB:
            evalBinaryMath(Type.DOUBLE, frame);
            break;
        case IMUL:
            evalBinaryMath(Type.INTEGER, frame);
            break;
        case LMUL:
            evalBinaryMath(Type.LONG, frame);
            break;
        case FMUL:
            evalBinaryMath(Type.FLOAT, frame);
            break;
        case DMUL:
            evalBinaryMath(Type.DOUBLE, frame);
            break;
        case IDIV:
            evalBinaryMath(Type.INTEGER, frame);
            break;
        case LDIV:
            evalBinaryMath(Type.LONG, frame);
            break;
        case FDIV:
            evalBinaryMath(Type.FLOAT, frame);
            break;
        case DDIV:
            evalBinaryMath(Type.DOUBLE, frame);
            break;
        case IREM:
            evalBinaryMath(Type.INTEGER, frame);
            break;
        case LREM:
            evalBinaryMath(Type.LONG, frame);
            break;
        case FREM:
            evalBinaryMath(Type.FLOAT, frame);
            break;
        case DREM:
            evalBinaryMath(Type.DOUBLE, frame);
            break;
        // Unary
        case INEG:
            verifyAssignable(Type.INTEGER, simplePeek(frame));
            break;
        case LNEG:
            verifyAssignable(Type.LONG, simplePeek(frame));
            break;
        case FNEG:
            verifyAssignable(Type.FLOAT, simplePeek(frame));
            break;
        case DNEG:
            verifyAssignable(Type.DOUBLE, simplePeek(frame));
            break;
        // Shifts
        case ISHL:
            evalShift(Type.INTEGER, frame);
            break;
        case LSHL:
            evalShift(Type.LONG, frame);
            break;
        case ISHR:
            evalShift(Type.INTEGER, frame);
            break;
        case LSHR:
            evalShift(Type.LONG, frame);
            break;
        case IUSHR:
            evalShift(Type.INTEGER, frame);
            break;
        case LUSHR:
            evalShift(Type.LONG, frame);
            break;
        // Bitwise Math
        case IAND:
            evalBinaryMath(Type.INTEGER, frame);
            break;
        case LAND:
            evalBinaryMath(Type.LONG, frame);
            break;
        case IOR:
            evalBinaryMath(Type.INTEGER, frame);
            break;
        case LOR:
            evalBinaryMath(Type.LONG, frame);
            break;
        case IXOR:
            evalBinaryMath(Type.INTEGER, frame);
            break;
        case LXOR:
            evalBinaryMath(Type.LONG, frame);
            break;
        case IINC:
            {
                int index = iter.byteAt(pos + 1);
                verifyAssignable(Type.INTEGER, frame.getLocal(index));
                access(index, Type.INTEGER, subroutine);
                break;
            }
        // Conversion
        case I2L:
            verifyAssignable(Type.INTEGER, simplePop(frame));
            simplePush(Type.LONG, frame);
            break;
        case I2F:
            verifyAssignable(Type.INTEGER, simplePop(frame));
            simplePush(Type.FLOAT, frame);
            break;
        case I2D:
            verifyAssignable(Type.INTEGER, simplePop(frame));
            simplePush(Type.DOUBLE, frame);
            break;
        case L2I:
            verifyAssignable(Type.LONG, simplePop(frame));
            simplePush(Type.INTEGER, frame);
            break;
        case L2F:
            verifyAssignable(Type.LONG, simplePop(frame));
            simplePush(Type.FLOAT, frame);
            break;
        case L2D:
            verifyAssignable(Type.LONG, simplePop(frame));
            simplePush(Type.DOUBLE, frame);
            break;
        case F2I:
            verifyAssignable(Type.FLOAT, simplePop(frame));
            simplePush(Type.INTEGER, frame);
            break;
        case F2L:
            verifyAssignable(Type.FLOAT, simplePop(frame));
            simplePush(Type.LONG, frame);
            break;
        case F2D:
            verifyAssignable(Type.FLOAT, simplePop(frame));
            simplePush(Type.DOUBLE, frame);
            break;
        case D2I:
            verifyAssignable(Type.DOUBLE, simplePop(frame));
            simplePush(Type.INTEGER, frame);
            break;
        case D2L:
            verifyAssignable(Type.DOUBLE, simplePop(frame));
            simplePush(Type.LONG, frame);
            break;
        case D2F:
            verifyAssignable(Type.DOUBLE, simplePop(frame));
            simplePush(Type.FLOAT, frame);
            break;
        case I2B:
        case I2C:
        case I2S:
            verifyAssignable(Type.INTEGER, frame.peek());
            break;
        case LCMP:
            verifyAssignable(Type.LONG, simplePop(frame));
            verifyAssignable(Type.LONG, simplePop(frame));
            frame.push(Type.INTEGER);
            break;
        case FCMPL:
        case FCMPG:
            verifyAssignable(Type.FLOAT, simplePop(frame));
            verifyAssignable(Type.FLOAT, simplePop(frame));
            frame.push(Type.INTEGER);
            break;
        case DCMPL:
        case DCMPG:
            verifyAssignable(Type.DOUBLE, simplePop(frame));
            verifyAssignable(Type.DOUBLE, simplePop(frame));
            frame.push(Type.INTEGER);
            break;
        // Control flow
        case IFEQ:
        case IFNE:
        case IFLT:
        case IFGE:
        case IFGT:
        case IFLE:
            verifyAssignable(Type.INTEGER, simplePop(frame));
            break;
        case IF_ICMPEQ:
        case IF_ICMPNE:
        case IF_ICMPLT:
        case IF_ICMPGE:
        case IF_ICMPGT:
        case IF_ICMPLE:
            verifyAssignable(Type.INTEGER, simplePop(frame));
            verifyAssignable(Type.INTEGER, simplePop(frame));
            break;
        case IF_ACMPEQ:
        case IF_ACMPNE:
            verifyAssignable(Type.OBJECT, simplePop(frame));
            verifyAssignable(Type.OBJECT, simplePop(frame));
            break;
        case GOTO:
            break;
        case JSR:
            frame.push(Type.RETURN_ADDRESS);
            break;
        case RET:
            verifyAssignable(Type.RETURN_ADDRESS, frame.getLocal(iter.byteAt(pos + 1)));
            break;
        case TABLESWITCH:
        case LOOKUPSWITCH:
        case IRETURN:
            verifyAssignable(Type.INTEGER, simplePop(frame));
            break;
        case LRETURN:
            verifyAssignable(Type.LONG, simplePop(frame));
            break;
        case FRETURN:
            verifyAssignable(Type.FLOAT, simplePop(frame));
            break;
        case DRETURN:
            verifyAssignable(Type.DOUBLE, simplePop(frame));
            break;
        case ARETURN:
            try {
                CtClass returnType = Descriptor.getReturnType(method.getDescriptor(), classPool);
                verifyAssignable(Type.get(returnType), simplePop(frame));
            } catch (NotFoundException e) {
                throw new RuntimeException(e);
            }
            break;
        case RETURN:
            break;
        case GETSTATIC:
            evalGetField(opcode, iter.u16bitAt(pos + 1), frame);
            break;
        case PUTSTATIC:
            evalPutField(opcode, iter.u16bitAt(pos + 1), frame);
            break;
        case GETFIELD:
            evalGetField(opcode, iter.u16bitAt(pos + 1), frame);
            break;
        case PUTFIELD:
            evalPutField(opcode, iter.u16bitAt(pos + 1), frame);
            break;
        case INVOKEVIRTUAL:
        case INVOKESPECIAL:
        case INVOKESTATIC:
            evalInvokeMethod(opcode, iter.u16bitAt(pos + 1), frame);
            break;
        case INVOKEINTERFACE:
            evalInvokeIntfMethod(opcode, iter.u16bitAt(pos + 1), frame);
            break;
        case INVOKEDYNAMIC:
            evalInvokeDynamic(opcode, iter.u16bitAt(pos + 1), frame);
            break;
        case NEW:
            frame.push(resolveClassInfo(constPool.getClassInfo(iter.u16bitAt(pos + 1))));
            break;
        case NEWARRAY:
            evalNewArray(pos, iter, frame);
            break;
        case ANEWARRAY:
            evalNewObjectArray(pos, iter, frame);
            break;
        case ARRAYLENGTH:
            {
                Type array = simplePop(frame);
                if (!array.isArray() && array != Type.UNINIT)
                    throw new BadBytecode("Array length passed a non-array [pos = " + pos + "]: " + array);
                frame.push(Type.INTEGER);
                break;
            }
        case ATHROW:
            verifyAssignable(THROWABLE_TYPE, simplePop(frame));
            break;
        case CHECKCAST:
            verifyAssignable(Type.OBJECT, simplePop(frame));
            frame.push(typeFromDesc(constPool.getClassInfoByDescriptor(iter.u16bitAt(pos + 1))));
            break;
        case INSTANCEOF:
            verifyAssignable(Type.OBJECT, simplePop(frame));
            frame.push(Type.INTEGER);
            break;
        case MONITORENTER:
        case MONITOREXIT:
            verifyAssignable(Type.OBJECT, simplePop(frame));
            break;
        case WIDE:
            evalWide(pos, iter, frame, subroutine);
            break;
        case MULTIANEWARRAY:
            evalNewObjectArray(pos, iter, frame);
            break;
        case IFNULL:
        case IFNONNULL:
            verifyAssignable(Type.OBJECT, simplePop(frame));
            break;
        case GOTO_W:
            break;
        case JSR_W:
            frame.push(Type.RETURN_ADDRESS);
            break;
    }
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) NotFoundException(org.hotswap.agent.javassist.NotFoundException) BadBytecode(org.hotswap.agent.javassist.bytecode.BadBytecode)

Example 53 with CtClass

use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.

the class MultiArrayType method getCtClass.

public CtClass getCtClass() {
    CtClass clazz = component.getCtClass();
    if (clazz == null)
        return null;
    ClassPool pool = clazz.getClassPool();
    if (pool == null)
        pool = ClassPool.getDefault();
    String name = arrayName(clazz.getName(), dims);
    try {
        return pool.get(name);
    } catch (NotFoundException e) {
        throw new RuntimeException(e);
    }
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) ClassPool(org.hotswap.agent.javassist.ClassPool) NotFoundException(org.hotswap.agent.javassist.NotFoundException)

Example 54 with CtClass

use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.

the class MultiType method isAssignableTo.

public boolean isAssignableTo(Type type) {
    if (resolved != null)
        return type.isAssignableFrom(resolved);
    if (Type.OBJECT.equals(type))
        return true;
    if (potentialClass != null && !type.isAssignableFrom(potentialClass))
        potentialClass = null;
    Map map = mergeMultiAndSingle(this, type);
    if (map.size() == 1 && potentialClass == null) {
        // Update previous merge paths to the same resolved type
        resolved = Type.get((CtClass) map.values().iterator().next());
        propogateResolved();
        return true;
    }
    // Keep all previous merge paths up to date
    if (map.size() >= 1) {
        interfaces = map;
        propogateState();
        return true;
    }
    if (potentialClass != null) {
        resolved = potentialClass;
        propogateResolved();
        return true;
    }
    return false;
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) Map(java.util.Map) HashMap(java.util.HashMap)

Example 55 with CtClass

use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.

the class MultiType method merge.

public Type merge(Type type) {
    if (this == type)
        return this;
    if (type == UNINIT)
        return this;
    if (type == BOGUS)
        return BOGUS;
    if (type == null)
        return this;
    if (resolved != null)
        return resolved.merge(type);
    if (potentialClass != null) {
        Type mergePotential = potentialClass.merge(type);
        if (!mergePotential.equals(potentialClass) || mergePotential.popChanged()) {
            potentialClass = Type.OBJECT.equals(mergePotential) ? null : mergePotential;
            changed = true;
        }
    }
    Map merged;
    if (type instanceof MultiType) {
        MultiType multi = (MultiType) type;
        if (multi.resolved != null) {
            merged = mergeMultiAndSingle(this, multi.resolved);
        } else {
            merged = mergeMultiInterfaces(multi, this);
            if (!inMergeSource(multi))
                mergeSource = multi;
        }
    } else {
        merged = mergeMultiAndSingle(this, type);
    }
    // Keep all previous merge paths up to date
    if (merged.size() > 1 || (merged.size() == 1 && potentialClass != null)) {
        // Check for changes
        if (merged.size() != interfaces.size()) {
            changed = true;
        } else if (changed == false) {
            Iterator iter = merged.keySet().iterator();
            while (iter.hasNext()) if (!interfaces.containsKey(iter.next()))
                changed = true;
        }
        interfaces = merged;
        propogateState();
        return this;
    }
    if (merged.size() == 1) {
        resolved = Type.get((CtClass) merged.values().iterator().next());
    } else if (potentialClass != null) {
        resolved = potentialClass;
    } else {
        resolved = OBJECT;
    }
    propogateResolved();
    return resolved;
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) Iterator(java.util.Iterator) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

CtClass (org.hotswap.agent.javassist.CtClass)69 NotFoundException (org.hotswap.agent.javassist.NotFoundException)20 CtMethod (org.hotswap.agent.javassist.CtMethod)18 ClassPool (org.hotswap.agent.javassist.ClassPool)14 OnClassLoadEvent (org.hotswap.agent.annotation.OnClassLoadEvent)13 CannotCompileException (org.hotswap.agent.javassist.CannotCompileException)8 CtConstructor (org.hotswap.agent.javassist.CtConstructor)8 CtField (org.hotswap.agent.javassist.CtField)8 HashMap (java.util.HashMap)6 LoaderClassPath (org.hotswap.agent.javassist.LoaderClassPath)6 IOException (java.io.IOException)5 ArrayList (java.util.ArrayList)5 Map (java.util.Map)5 Test (org.junit.Test)5 Iterator (java.util.Iterator)4 ExprEditor (org.hotswap.agent.javassist.expr.ExprEditor)4 Method (java.lang.reflect.Method)3 IdentityHashMap (java.util.IdentityHashMap)3 BadBytecode (org.hotswap.agent.javassist.bytecode.BadBytecode)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2