1
2
3
4
5
6
7
8
9
10 package nl.tudelft.simulation.dsol.interpreter.operations.reflection;
11
12 import java.io.DataInput;
13 import java.io.IOException;
14 import java.lang.reflect.Method;
15
16 import nl.tudelft.simulation.dsol.interpreter.Frame;
17 import nl.tudelft.simulation.dsol.interpreter.InterpreterException;
18 import nl.tudelft.simulation.dsol.interpreter.classfile.ConstantMethodref;
19 import nl.tudelft.simulation.dsol.interpreter.operations.InvokeOperation;
20 import nl.tudelft.simulation.language.primitives.Primitive;
21 import nl.tudelft.simulation.language.reflection.ClassUtil;
22 import nl.tudelft.simulation.language.reflection.MethodSignature;
23
24 /***
25 * INVOKEVIRTUAL <br>
26 * (c) copyright 2003 <a href="http://www.simulation.tudelft.nl">Delft
27 * University of Technology </a>, the Netherlands. <br>
28 * See for project information <a
29 * href="http://www.simulation.tudelft.nl">www.simulation.tudelft.nl </a> <br>
30 * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
31 * License (GPL) </a>, no warranty <br>
32 *
33 * @version 1.0 Jan 8, 2004 <br>
34 * @author <a href="http://www.tbm.tudelft.nl/webstaf/peterja/index.htm">Peter
35 * Jacobs </a> <br>
36 * <a
37 * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
38 * Verbraeck </a>
39 */
40 public class INVOKEVIRTUAL extends InvokeOperation
41 {
42 /*** OP refers to the operand code */
43 public static final int OP = 182;
44
45 /*** the index to load */
46 protected int index = -1;
47
48 /***
49 * constructs a new INVOKEVIRTUAL
50 *
51 * @param dataInput the dataInput
52 * @throws IOException on IOfailure
53 */
54 public INVOKEVIRTUAL(final DataInput dataInput) throws IOException
55 {
56 super();
57 this.index = dataInput.readUnsignedShort();
58 }
59
60 /***
61 * @see nl.tudelft.simulation.dsol.interpreter.operations.InvokeOperation
62 * #execute(nl.tudelft.simulation.dsol.interpreter.Frame)
63 */
64 public Frame execute(final Frame frame)
65 {
66 try
67 {
68
69
70 ConstantMethodref constantMethodref = (ConstantMethodref) frame
71 .getConstantPool()[this.index];
72
73 Class[] parameterTypes = new MethodSignature(constantMethodref
74 .getConstantNameAndType().getDescriptor())
75 .getParameterTypes();
76
77 synchronized (frame.getOperandStack())
78 {
79
80 Object objectRef = frame.getOperandStack().peek(
81 parameterTypes.length);
82
83 Method method = ClassUtil.resolveMethod(objectRef,
84 constantMethodref.getConstantNameAndType().getName(),
85 parameterTypes);
86
87
88 Object[] args = new Object[parameterTypes.length];
89 for (int i = args.length - 1; i > -1; i--)
90 {
91 args[i] = Primitive.cast(parameterTypes[i], frame
92 .getOperandStack().pop());
93 }
94
95 frame.getOperandStack().pop();
96 return this.execute(frame, objectRef, method, args);
97 }
98 } catch (Exception exception)
99 {
100 throw new InterpreterException(exception);
101 }
102 }
103
104 /***
105 * executes the method on the objectRef
106 *
107 * @param frame the frame
108 * @param objectRef the objectRef
109 * @param method the method
110 * @param arguments the arguments
111 * @return the resulting Frame
112 * @throws Exception on reflection exception
113 */
114 public Frame execute(final Frame frame, final Object objectRef,
115 final Method method, final Object[] arguments) throws Exception
116 {
117 method.setAccessible(true);
118 Object result = method.invoke(objectRef, arguments);
119
120
121 if (!method.getReturnType().equals(void.class))
122 {
123 frame.getOperandStack().push(result);
124 }
125 return null;
126 }
127
128 /***
129 * @see nl.tudelft.simulation.dsol.interpreter.Operation#getByteLength()
130 */
131 public int getByteLength()
132 {
133 return OPCODE_BYTE_LENGTH + 2;
134 }
135
136 /***
137 * @see nl.tudelft.simulation.dsol.interpreter.Operation#getOpcode()
138 */
139 public int getOpcode()
140 {
141 return INVOKEVIRTUAL.OP;
142 }
143 }