|
|
@ -18,6 +18,9 @@ |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
package jode.jvm; |
|
|
|
package jode.jvm; |
|
|
|
import jode.bytecode.*; |
|
|
|
import jode.bytecode.*; |
|
|
|
|
|
|
|
import jode.decompiler.ClassAnalyzer; |
|
|
|
|
|
|
|
import jode.MethodType; |
|
|
|
|
|
|
|
import jode.Type; |
|
|
|
import java.lang.reflect.*; |
|
|
|
import java.lang.reflect.*; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -28,14 +31,109 @@ import java.lang.reflect.*; |
|
|
|
* @author Jochen Hoenicke |
|
|
|
* @author Jochen Hoenicke |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class Interpreter implements Opcodes { |
|
|
|
public class Interpreter implements Opcodes { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int checkType(String typesig, int pos, Class type) { |
|
|
|
|
|
|
|
switch (typesig.charAt(pos++)) { |
|
|
|
|
|
|
|
case 'Z': |
|
|
|
|
|
|
|
if (type != Boolean.TYPE) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'B': |
|
|
|
|
|
|
|
if (type != Byte.TYPE) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'C': |
|
|
|
|
|
|
|
if (type != Character.TYPE) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'S': |
|
|
|
|
|
|
|
if (type != Short.TYPE) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'I': |
|
|
|
|
|
|
|
if (type != Integer.TYPE) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'J': |
|
|
|
|
|
|
|
if (type != Long.TYPE) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'F': |
|
|
|
|
|
|
|
if (type != Float.TYPE) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'D': |
|
|
|
|
|
|
|
if (type != Double.TYPE) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'V': |
|
|
|
|
|
|
|
if (type != Void.TYPE) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case '[': |
|
|
|
|
|
|
|
if (!type.isArray()) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
pos = checkType(typesig, pos, type.getComponentType()); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 'L': { |
|
|
|
|
|
|
|
int index = typesig.indexOf(';', pos); |
|
|
|
|
|
|
|
if (index == -1) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
if (!type.getName().replace('.','/') |
|
|
|
|
|
|
|
.equals(typesig.substring(pos, index))) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
pos = index+1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return pos; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static boolean checkMethod(String typesig, |
|
|
|
|
|
|
|
Class[] paramTypes, Class retType) { |
|
|
|
|
|
|
|
if (typesig.charAt(0) != '(') |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
int pos = 1; |
|
|
|
|
|
|
|
int i = 0; |
|
|
|
|
|
|
|
while (typesig.charAt(pos) != ')') { |
|
|
|
|
|
|
|
if (i >= paramTypes.length) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
pos = checkType(typesig, pos, paramTypes[i++]); |
|
|
|
|
|
|
|
if (pos == -1) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (i != paramTypes.length) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
pos++; |
|
|
|
|
|
|
|
pos = checkType(typesig, pos, retType); |
|
|
|
|
|
|
|
return pos == typesig.length(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static Object interpretMethod |
|
|
|
public static Object interpretMethod |
|
|
|
(ClassInfo currentClass, byte[] code, Value[] locals, Value[] stack) |
|
|
|
(ClassAnalyzer ca, byte[] code, Value[] locals, Value[] stack) |
|
|
|
throws InterpreterException, ClassFormatException { |
|
|
|
throws InterpreterException, ClassFormatException { |
|
|
|
try { |
|
|
|
try { |
|
|
|
ConstantPool cpool = currentClass.getConstantPool(); |
|
|
|
ConstantPool cpool = ca.getClazz().getConstantPool(); |
|
|
|
int pc = 0; |
|
|
|
int pc = 0; |
|
|
|
int stacktop = 0; |
|
|
|
int stacktop = 0; |
|
|
|
for(;;) { |
|
|
|
for(;;) { |
|
|
|
|
|
|
|
// System.err.print(pc+": [");
|
|
|
|
|
|
|
|
// for (int i=0; i<stacktop; i++) {
|
|
|
|
|
|
|
|
// if (i>0)
|
|
|
|
|
|
|
|
// System.err.print(",");
|
|
|
|
|
|
|
|
// System.err.print(stack[i]);
|
|
|
|
|
|
|
|
// if (stack[i].objectValue() instanceof char[]) {
|
|
|
|
|
|
|
|
// System.err.print(new String((char[])stack[i].objectValue()));
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// System.err.println("]");
|
|
|
|
|
|
|
|
// System.err.print("local: [");
|
|
|
|
|
|
|
|
// for (int i=0; i<locals.length; i++)
|
|
|
|
|
|
|
|
// System.err.print(locals[i]+",");
|
|
|
|
|
|
|
|
// System.err.println("]");
|
|
|
|
int opcode = code[pc++] & 0xff; |
|
|
|
int opcode = code[pc++] & 0xff; |
|
|
|
switch (opcode) { |
|
|
|
switch (opcode) { |
|
|
|
case opc_nop: |
|
|
|
case opc_nop: |
|
|
@ -97,8 +195,10 @@ public class Interpreter implements Opcodes { |
|
|
|
Object array = stack[--stacktop].objectValue(); |
|
|
|
Object array = stack[--stacktop].objectValue(); |
|
|
|
switch(opcode) { |
|
|
|
switch(opcode) { |
|
|
|
case opc_baload: |
|
|
|
case opc_baload: |
|
|
|
stack[stacktop++].setInt(((byte[])array)[index]); |
|
|
|
stack[stacktop++].setInt |
|
|
|
break; |
|
|
|
(array instanceof byte[] |
|
|
|
|
|
|
|
? ((byte[])array)[index] |
|
|
|
|
|
|
|
: ((boolean[])array)[index] ? 1 : 0); |
|
|
|
case opc_caload: |
|
|
|
case opc_caload: |
|
|
|
stack[stacktop++].setInt(((char[])array)[index]); |
|
|
|
stack[stacktop++].setInt(((char[])array)[index]); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -106,19 +206,11 @@ public class Interpreter implements Opcodes { |
|
|
|
stack[stacktop++].setInt(((short[])array)[index]); |
|
|
|
stack[stacktop++].setInt(((short[])array)[index]); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case opc_iaload: |
|
|
|
case opc_iaload: |
|
|
|
stack[stacktop++].setInt(((int[])array)[index]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case opc_laload: |
|
|
|
case opc_laload: |
|
|
|
stack[stacktop++].setLong(((long[])array)[index]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case opc_faload: |
|
|
|
case opc_faload: |
|
|
|
stack[stacktop++].setFloat(((float[])array)[index]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case opc_daload: |
|
|
|
case opc_daload: |
|
|
|
stack[stacktop++].setDouble(((double[])array)[index]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case opc_aaload: |
|
|
|
case opc_aaload: |
|
|
|
stack[stacktop++].setObject(((Object[])array)[index]); |
|
|
|
stack[stacktop++].setObject(Array.get(array, index)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
@ -146,30 +238,24 @@ public class Interpreter implements Opcodes { |
|
|
|
int index = stack[--stacktop].intValue(); |
|
|
|
int index = stack[--stacktop].intValue(); |
|
|
|
Object array = stack[--stacktop].objectValue(); |
|
|
|
Object array = stack[--stacktop].objectValue(); |
|
|
|
switch(opcode) { |
|
|
|
switch(opcode) { |
|
|
|
case opc_baload: |
|
|
|
case opc_bastore: |
|
|
|
((byte[])array)[index] = (byte) value.intValue(); |
|
|
|
if (array instanceof byte[]) |
|
|
|
|
|
|
|
((byte[])array)[index] = (byte) value.intValue(); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
((boolean[])array)[index] = value.intValue() != 0; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case opc_caload: |
|
|
|
case opc_castore: |
|
|
|
((char[])array)[index] = (char) value.intValue(); |
|
|
|
((char[])array)[index] = (char) value.intValue(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case opc_saload: |
|
|
|
case opc_sastore: |
|
|
|
((short[])array)[index] = (short) value.intValue(); |
|
|
|
((short[])array)[index] = (short) value.intValue(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case opc_iaload: |
|
|
|
case opc_iastore: |
|
|
|
((int[])array)[index] = value.intValue(); |
|
|
|
case opc_lastore: |
|
|
|
break; |
|
|
|
case opc_fastore: |
|
|
|
case opc_laload: |
|
|
|
case opc_dastore: |
|
|
|
((long[])array)[index] = value.longValue(); |
|
|
|
case opc_aastore: |
|
|
|
break; |
|
|
|
Array.set(array, index, value.objectValue()); |
|
|
|
case opc_faload: |
|
|
|
|
|
|
|
((float[])array)[index] = value.floatValue(); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case opc_daload: |
|
|
|
|
|
|
|
((double[])array)[index] = value.doubleValue(); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case opc_aaload: |
|
|
|
|
|
|
|
((Object[])array)[index] = value.objectValue(); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -177,25 +263,27 @@ public class Interpreter implements Opcodes { |
|
|
|
stacktop -= opcode - (opc_pop-1); |
|
|
|
stacktop -= opcode - (opc_pop-1); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case opc_dup: case opc_dup_x1: case opc_dup_x2: { |
|
|
|
case opc_dup: case opc_dup_x1: case opc_dup_x2: { |
|
|
|
int depth = (opcode - opc_dup)%3; |
|
|
|
int depth = opcode - opc_dup; |
|
|
|
for (int i=0; i < depth+1; i++) |
|
|
|
for (int i=0; i < depth+1; i++) |
|
|
|
stack[stacktop+1-i].setValue(stack[stacktop-i]); |
|
|
|
stack[stacktop-i].setValue(stack[stacktop-i-1]); |
|
|
|
stack[stacktop-depth].setValue(stack[stacktop]); |
|
|
|
stack[stacktop-depth-1].setValue(stack[stacktop]); |
|
|
|
stacktop++; |
|
|
|
stacktop++; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: { |
|
|
|
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: { |
|
|
|
int depth = (opcode - opc_dup)%3; |
|
|
|
int depth = opcode - opc_dup2; |
|
|
|
for (int i=0; i < depth+2; i++) |
|
|
|
for (int i=0; i < depth+2; i++) |
|
|
|
stack[stacktop+2-i] = stack[stacktop-i]; |
|
|
|
stack[stacktop+1-i].setValue(stack[stacktop-1-i]); |
|
|
|
stack[stacktop-depth].setValue(stack[stacktop+1]); |
|
|
|
stack[stacktop-depth-1].setValue(stack[stacktop+1]); |
|
|
|
stack[stacktop-depth-1].setValue(stack[stacktop]); |
|
|
|
stack[stacktop-depth-2].setValue(stack[stacktop]); |
|
|
|
stacktop += 2; |
|
|
|
stacktop += 2; |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_swap: { |
|
|
|
case opc_swap: { |
|
|
|
Value tmp = stack[stacktop-1]; |
|
|
|
Value tmp = stack[stacktop-1]; |
|
|
|
stack[stacktop-1] = stack[stacktop-2]; |
|
|
|
stack[stacktop-1] = stack[stacktop-2]; |
|
|
|
stack[stacktop-2] = tmp; |
|
|
|
stack[stacktop-2] = tmp; |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_iadd: |
|
|
|
case opc_iadd: |
|
|
|
stack[stacktop-2].setInt(stack[stacktop-2].intValue() |
|
|
|
stack[stacktop-2].setInt(stack[stacktop-2].intValue() |
|
|
@ -506,7 +594,7 @@ public class Interpreter implements Opcodes { |
|
|
|
|| value < 0 && (opcode == opc_iflt || opcode == opc_ifle) |
|
|
|
|| value < 0 && (opcode == opc_iflt || opcode == opc_ifle) |
|
|
|
|| value == 0 && (opcode == opc_ifge || opcode == opc_ifle |
|
|
|
|| value == 0 && (opcode == opc_ifge || opcode == opc_ifle |
|
|
|
|| opcode == opc_ifeq)) |
|
|
|
|| opcode == opc_ifeq)) |
|
|
|
pc += opcode; |
|
|
|
pc += offset; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_jsr: |
|
|
|
case opc_jsr: |
|
|
@ -523,12 +611,16 @@ public class Interpreter implements Opcodes { |
|
|
|
int value = stack[--stacktop].intValue(); |
|
|
|
int value = stack[--stacktop].intValue(); |
|
|
|
int start = pc - 1; |
|
|
|
int start = pc - 1; |
|
|
|
pc += 3-(start % 4); |
|
|
|
pc += 3-(start % 4); |
|
|
|
int dest = ((code[pc++] << 8) | (code[pc++] & 0xff)); |
|
|
|
int dest = (code[pc++] << 24 | (code[pc++] & 0xff) << 16 |
|
|
|
int low = ((code[pc++] << 8) | (code[pc++] & 0xff)); |
|
|
|
| (code[pc++] & 0xff) << 8 | (code[pc++] & 0xff)); |
|
|
|
int high = ((code[pc++] << 8) | (code[pc++] & 0xff)); |
|
|
|
int low = (code[pc++] << 24 | (code[pc++] & 0xff) << 16 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff) << 8 | (code[pc++] & 0xff)); |
|
|
|
|
|
|
|
int high = (code[pc++] << 24 | (code[pc++] & 0xff) << 16 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff) << 8 | (code[pc++] & 0xff)); |
|
|
|
if (value >= low && value <= high) { |
|
|
|
if (value >= low && value <= high) { |
|
|
|
pc += (value - low) << 1; |
|
|
|
pc += (value - low) << 2; |
|
|
|
dest = ((code[pc] << 8) | (code[pc+1] & 0xff)); |
|
|
|
dest = (code[pc++] << 24 | (code[pc++] & 0xff) << 16 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff) << 8 | (code[pc++] & 0xff)); |
|
|
|
} |
|
|
|
} |
|
|
|
pc = start + dest; |
|
|
|
pc = start + dest; |
|
|
|
break; |
|
|
|
break; |
|
|
@ -537,11 +629,23 @@ public class Interpreter implements Opcodes { |
|
|
|
int value = stack[--stacktop].intValue(); |
|
|
|
int value = stack[--stacktop].intValue(); |
|
|
|
int start = pc - 1; |
|
|
|
int start = pc - 1; |
|
|
|
pc += 3-(start % 4); |
|
|
|
pc += 3-(start % 4); |
|
|
|
int dest = ((code[pc++] << 8) | (code[pc++] & 0xff)); |
|
|
|
int dest = (code[pc++] << 24 |
|
|
|
int npairs = ((code[pc++] << 8) | (code[pc++] & 0xff)); |
|
|
|
| (code[pc++] & 0xff) << 16 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff) << 8 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff)); |
|
|
|
|
|
|
|
int npairs = (code[pc++] << 24 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff) << 16 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff) << 8 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff)); |
|
|
|
for (int i=0; i < npairs; i++) { |
|
|
|
for (int i=0; i < npairs; i++) { |
|
|
|
if (value == ((code[pc++] << 8) | (code[pc++] & 0xff))) { |
|
|
|
if (value == (code[pc++] << 24 |
|
|
|
dest = ((code[pc++] << 8) | (code[pc++] & 0xff)); |
|
|
|
| (code[pc++] & 0xff) << 16 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff) << 8 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff))) { |
|
|
|
|
|
|
|
dest = (code[pc++] << 24 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff) << 16 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff) << 8 |
|
|
|
|
|
|
|
| (code[pc++] & 0xff)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
pc+=2; |
|
|
|
pc+=2; |
|
|
@ -569,84 +673,102 @@ public class Interpreter implements Opcodes { |
|
|
|
int argcount= (opcode == opc_invokeinterface) |
|
|
|
int argcount= (opcode == opc_invokeinterface) |
|
|
|
? (code[pc++] << 8) | (code[pc++] & 0xff) : -1; |
|
|
|
? (code[pc++] << 8) | (code[pc++] & 0xff) : -1; |
|
|
|
|
|
|
|
|
|
|
|
// if (ref[0] == currentClass.getName()) {
|
|
|
|
if (ref[0].equals(ca.getClazz().getName().replace('.','/'))) { |
|
|
|
// /* invoke interpreter again */
|
|
|
|
boolean isStatic = opcode == opc_invokestatic; |
|
|
|
// } else {
|
|
|
|
MethodType mt = new MethodType(isStatic, ref[2]); |
|
|
|
Class clazz; |
|
|
|
CodeInfo info = ca.getMethod(ref[1], mt) |
|
|
|
try { |
|
|
|
.getCode().getCodeInfo(); |
|
|
|
clazz = Class.forName |
|
|
|
Value[] newLocals = new Value[info.getMaxLocals()]; |
|
|
|
(cpool.getClassName((code[pc++] << 8) & 0xff00 |
|
|
|
for (int i=0; i< newLocals.length; i++) |
|
|
|
| code[pc++] & 0xff) |
|
|
|
newLocals[i] = new Value(); |
|
|
|
.replace('/','.')); |
|
|
|
Value[] newStack = new Value[info.getMaxStack()]; |
|
|
|
} catch (ClassNotFoundException ex) { |
|
|
|
for (int i=0; i< newStack.length; i++) |
|
|
|
throw new InterpreterException |
|
|
|
newStack[i] = new Value(); |
|
|
|
("Class "+ref[0]+" not found"); |
|
|
|
for (int i=mt.getParameterTypes().length - 1; i >= 0; i--) |
|
|
|
} |
|
|
|
newLocals[i].setValue(stack[--stacktop]); |
|
|
|
try { |
|
|
|
Object result = interpretMethod(ca, info.getCode(), |
|
|
|
if (ref[1].equals("<init>")) { |
|
|
|
newLocals, newStack); |
|
|
|
Constructor[] cs = clazz.getConstructors(); |
|
|
|
if (mt.getReturnType() != Type.tVoid) { |
|
|
|
Constructor c = null; |
|
|
|
stack[stacktop++].setObject(result); |
|
|
|
for (int i=0; i< cs.length; i++) { |
|
|
|
} |
|
|
|
/* check types XXX */ |
|
|
|
} else { |
|
|
|
c = cs[i]; |
|
|
|
Class clazz; |
|
|
|
break; |
|
|
|
try { |
|
|
|
} |
|
|
|
clazz = Class.forName(ref[0].replace('/','.')); |
|
|
|
|
|
|
|
} catch (ClassNotFoundException ex) { |
|
|
|
|
|
|
|
throw new InterpreterException |
|
|
|
|
|
|
|
("Class "+ref[0]+" not found"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
if (ref[1].equals("<init>")) { |
|
|
|
|
|
|
|
Constructor[] cs = clazz.getConstructors(); |
|
|
|
|
|
|
|
Constructor c = null; |
|
|
|
|
|
|
|
for (int i=0; i< cs.length; i++) { |
|
|
|
|
|
|
|
if (checkMethod(ref[2], cs[i].getParameterTypes(), |
|
|
|
|
|
|
|
Void.TYPE)) { |
|
|
|
|
|
|
|
c = cs[i]; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
if (c == null) |
|
|
|
if (c == null) |
|
|
|
throw new InterpreterException("Constructor " |
|
|
|
throw new InterpreterException("Constructor " |
|
|
|
+ref[0]+"." |
|
|
|
+ref[0]+"." |
|
|
|
+ref[1]+" not found."); |
|
|
|
+ref[1]+" not found."); |
|
|
|
Object[] args |
|
|
|
Object[] args |
|
|
|
= new Object[c.getParameterTypes().length]; |
|
|
|
= new Object[c.getParameterTypes().length]; |
|
|
|
for (int i=args.length - 1; i >= 0; i--) |
|
|
|
for (int i=args.length - 1; i >= 0; i--) |
|
|
|
args[i] = stack[--stacktop].objectValue(); |
|
|
|
args[i] = stack[--stacktop].objectValue(); |
|
|
|
NewObject newObj = |
|
|
|
NewObject newObj = stack[--stacktop].getNewObject(); |
|
|
|
(NewObject) stack[--stacktop].objectValue(); |
|
|
|
if (!newObj.getType().equals(ref[0])) |
|
|
|
if (!newObj.getClass().equals(ref[0])) |
|
|
|
|
|
|
|
throw new InterpreterException("constructor not called" |
|
|
|
throw new InterpreterException("constructor not called" |
|
|
|
+" on new instance"); |
|
|
|
+" on new instance"); |
|
|
|
newObj.setObject(c.newInstance(args)); |
|
|
|
newObj.setObject(c.newInstance(args)); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
Method[] ms = clazz.getMethods(); |
|
|
|
Method[] ms = clazz.getMethods(); |
|
|
|
Method m = null; |
|
|
|
Method m = null; |
|
|
|
for (int i=0; i< ms.length; i++) { |
|
|
|
for (int i=0; i< ms.length; i++) { |
|
|
|
if (ms[i].getName().equals(ref[1])) { |
|
|
|
if (ms[i].getName().equals(ref[1])) { |
|
|
|
/* check types XXX */ |
|
|
|
if (checkMethod(ref[2], |
|
|
|
m = ms[i]; |
|
|
|
ms[i].getParameterTypes(), |
|
|
|
break; |
|
|
|
ms[i].getReturnType())) { |
|
|
|
|
|
|
|
m = ms[i]; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (m == null) |
|
|
|
if (m == null) |
|
|
|
throw new InterpreterException("Method "+ref[0]+"." |
|
|
|
throw new InterpreterException("Method "+ref[0]+"." |
|
|
|
+ref[1]+" not found."); |
|
|
|
+ref[1]+" not found."); |
|
|
|
Object obj = null; |
|
|
|
Object obj = null; |
|
|
|
Object[] args |
|
|
|
Object[] args |
|
|
|
= new Object[m.getParameterTypes().length]; |
|
|
|
= new Object[m.getParameterTypes().length]; |
|
|
|
for (int i=args.length - 1; i >= 0; i--) |
|
|
|
for (int i=args.length - 1; i >= 0; i--) |
|
|
|
args[i] = stack[--stacktop].objectValue(); |
|
|
|
args[i] = stack[--stacktop].objectValue(); |
|
|
|
if (opcode != opc_invokestatic) |
|
|
|
if (opcode != opc_invokestatic) |
|
|
|
obj = stack[--stacktop].objectValue(); |
|
|
|
obj = stack[--stacktop].objectValue(); |
|
|
|
/* special and constructor? XXX*/ |
|
|
|
/* special and constructor? XXX*/ |
|
|
|
|
|
|
|
Object result = m.invoke(obj, args); |
|
|
|
Object result = m.invoke(obj, args); |
|
|
|
if (m.getReturnType() != Void.TYPE) |
|
|
|
if (m.getReturnType() != Void.TYPE) |
|
|
|
stack[stacktop++].setObject(result); |
|
|
|
stack[stacktop++].setObject(result); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} catch (IllegalAccessException ex) { |
|
|
|
|
|
|
|
throw new InterpreterException |
|
|
|
|
|
|
|
("Method "+ref[0]+"."+ref[1]+" not accessible"); |
|
|
|
|
|
|
|
} catch (InstantiationException ex) { |
|
|
|
|
|
|
|
throw new InterpreterException |
|
|
|
|
|
|
|
("InstantiationException in "+ref[0]+"."+ref[1]+"."); |
|
|
|
|
|
|
|
} catch (InvocationTargetException ex) { |
|
|
|
|
|
|
|
throw new InterpreterException |
|
|
|
|
|
|
|
("Method "+ref[0]+"."+ref[1]+" throwed an exception"); |
|
|
|
|
|
|
|
/*XXX exception handler?*/ |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (IllegalAccessException ex) { |
|
|
|
|
|
|
|
throw new InterpreterException |
|
|
|
|
|
|
|
("Method "+ref[0]+"."+ref[1]+" not accessible"); |
|
|
|
|
|
|
|
} catch (InstantiationException ex) { |
|
|
|
|
|
|
|
throw new InterpreterException |
|
|
|
|
|
|
|
("InstantiationException in "+ref[0]+"."+ref[1]+"."); |
|
|
|
|
|
|
|
} catch (InvocationTargetException ex) { |
|
|
|
|
|
|
|
throw new InterpreterException |
|
|
|
|
|
|
|
("Method "+ref[0]+"."+ref[1]+" throwed an exception"); |
|
|
|
|
|
|
|
/*XXX exception handler?*/ |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_new: { |
|
|
|
case opc_new: { |
|
|
|
String clazz = cpool.getClassName((code[pc++] << 8) & 0xff00 |
|
|
|
String clazz = cpool.getClassName((code[pc++] << 8) & 0xff00 |
|
|
|
| code[pc++] & 0xff); |
|
|
|
| code[pc++] & 0xff); |
|
|
|
stack[stacktop++].setObject(new NewObject(clazz)); |
|
|
|
stack[stacktop++].setNewObject(new NewObject(clazz)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_newarray: { |
|
|
|
case opc_newarray: { |
|
|
@ -805,6 +927,7 @@ public class Interpreter implements Opcodes { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} catch(RuntimeException ex) { |
|
|
|
} catch(RuntimeException ex) { |
|
|
|
|
|
|
|
ex.printStackTrace(); |
|
|
|
throw new InterpreterException("Caught RuntimeException: " |
|
|
|
throw new InterpreterException("Caught RuntimeException: " |
|
|
|
+ ex.toString()); |
|
|
|
+ ex.toString()); |
|
|
|
} |
|
|
|
} |
|
|
|