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());
}
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;
}
}
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);
}
}
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;
}
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;
}
Aggregations