2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.vm;
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.annotation.MJI;
22 import gov.nasa.jpf.util.MethodInfoRegistry;
23 import gov.nasa.jpf.util.RunListener;
24 import gov.nasa.jpf.util.RunRegistry;
26 import java.lang.reflect.Method;
27 import java.lang.reflect.Modifier;
28 import java.util.ArrayList;
30 public class JPF_java_lang_reflect_Method extends NativePeer {
32 static MethodInfoRegistry registry;
34 // class init - this is called automatically from the NativePeer ctor
35 public static boolean init (Config conf) {
36 // this is an example of how to handle cross-initialization between
37 // native peers - this might also get explicitly called by the java.lang.Class
38 // peer, since it creates Method objects. Here we have to make sure
39 // we only reset between JPF runs
41 if (registry == null){
42 registry = new MethodInfoRegistry();
44 RunRegistry.getDefaultRegistry().addListener( new RunListener() {
46 public void reset (RunRegistry reg){
54 static int createMethodObject (MJIEnv env, ClassInfo ciMth, MethodInfo mi){
55 // note - it is the callers responsibility to ensure Method is properly initialized
56 int regIdx = registry.registerMethodInfo(mi);
57 int eidx = env.newObject( ciMth);
58 ElementInfo ei = env.getModifiableElementInfo(eidx);
60 ei.setIntField("regIdx", regIdx);
61 ei.setBooleanField("isAccessible", mi.isPublic());
66 // this is NOT an MJI method, but it is used outside this package, so
67 // we have to add 'final'
68 public static final MethodInfo getMethodInfo (MJIEnv env, int objRef){
69 return registry.getMethodInfo(env,objRef, "regIdx");
73 public int getName____Ljava_lang_String_2 (MJIEnv env, int objRef) {
74 MethodInfo mi = getMethodInfo(env, objRef);
76 int nameRef = env.getReferenceField( objRef, "name");
77 if (nameRef == MJIEnv.NULL) {
78 nameRef = env.newString(mi.getName());
79 env.setReferenceField(objRef, "name", nameRef);
86 public int getModifiers____I (MJIEnv env, int objRef){
87 MethodInfo mi = getMethodInfo(env, objRef);
88 return mi.getModifiers();
91 static int getParameterTypes( MJIEnv env, MethodInfo mi) {
92 ThreadInfo ti = env.getThreadInfo();
93 String[] argTypeNames = mi.getArgumentTypeNames();
94 int[] ar = new int[argTypeNames.length];
96 for (int i = 0; i < argTypeNames.length; i++) {
97 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(argTypeNames[i]);
98 if (!ci.isRegistered()) {
102 ar[i] = ci.getClassObjectRef();
105 int aRef = env.newObjectArray("Ljava/lang/Class;", argTypeNames.length);
106 for (int i = 0; i < argTypeNames.length; i++) {
107 env.setReferenceArrayElement(aRef, i, ar[i]);
114 public int getParameterTypes_____3Ljava_lang_Class_2 (MJIEnv env, int objRef){
115 return getParameterTypes(env, getMethodInfo(env, objRef));
118 // TODO: Fix for Groovy's model-checking
119 private static int getGenericArrayTypeImplObj(String signature, MJIEnv env, int objRef, MethodInfo mi) {
121 ThreadInfo ti = env.getThreadInfo();
122 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
123 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl");
125 // Create a new object of type GenericArrayTypeImpl
126 int genArrRef = env.newObject(ci);
127 ElementInfo ei = env.getModifiableElementInfo(genArrRef);
129 // Get field information and fill out the fields
130 String clsSig = Types.getArrayClassName(signature);
132 if (Types.isParameterWithType(clsSig)) {
133 paramTypeRef = getTypeVariableImplObject(env, objRef, clsSig);
135 paramTypeRef = getParameterizedTypeImplObj(clsSig, env, objRef, mi);
137 ei.setReferenceField("genericComponentType", paramTypeRef);
142 private static int getParameterizedTypeImplObj(String signature, MJIEnv env, int objRef, MethodInfo mi) {
144 ThreadInfo ti = env.getThreadInfo();
145 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
146 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl");
147 // Create a new object of type ParameterizedTypeImpl
148 int paramTypeRef = env.newObject(ci);
149 ElementInfo ei = env.getModifiableElementInfo(paramTypeRef);
150 // Get field information and fill out the fields
152 String className = Types.getGenericClassName(signature);
153 ClassInfo gci = cli.getResolvedClassInfo(className);
154 if (!gci.isRegistered()) {
155 gci.registerClass(ti);
157 ei.setReferenceField("rawType", gci.getClassObjectRef());
159 // actualTypeArguments
160 String[] parameterizedTypes = Types.getParameterizedTypes(signature);
161 int[] types = new int[parameterizedTypes.length];
162 String classGenericSig = mi.getClassInfo().getGenericSignature();
163 String methodGenericSig = mi.getGenericSignature();
164 for(int j = 0; j < parameterizedTypes.length; j++) {
165 if (Types.isTypeParameter(parameterizedTypes[j], methodGenericSig) ||
166 Types.isTypeParameter(parameterizedTypes[j], classGenericSig)) {
167 types[j] = getTypeVariableImplObject(env, objRef, parameterizedTypes[j]);
168 } else if (Types.isWildcardType(parameterizedTypes[j])) {
169 types[j] = getWildcardTypeImplObject(env, objRef, parameterizedTypes[j], mi);
170 } else if (Types.isParameterizedType(parameterizedTypes[j])) {
172 types[j] = getParameterizedTypeImplObj(parameterizedTypes[j], env, objRef, mi);
174 ClassInfo pci = cli.getResolvedClassInfo(parameterizedTypes[j]);
175 if (!pci.isRegistered()) {
176 pci.registerClass(ti);
178 types[j] = pci.getClassObjectRef();
181 int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", parameterizedTypes.length);
182 // Set references for every array element
183 for (int j = 0; j < parameterizedTypes.length; j++) {
184 env.setReferenceArrayElement(aRef, j, types[j]);
186 ei.setReferenceField("actualTypeArguments", aRef);
189 String ownerType = Types.getOwnerClassName(signature);
190 if (ownerType != null) {
191 ClassInfo oci = ClassLoaderInfo.getCurrentResolvedClassInfo(ownerType);
192 if (!oci.isRegistered()) {
193 oci.registerClass(ti);
195 ei.setReferenceField("ownerType", oci.getClassObjectRef());
197 ei.setReferenceField("ownerType", MJIEnv.NULL);
203 private static int getWildcardTypeImplObject(MJIEnv env, int objRef, String wildcardType, MethodInfo mi) {
204 ThreadInfo ti = env.getThreadInfo();
205 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
206 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.WildcardTypeImpl");
208 int wildcardRef = env.newObject(ci);
209 ElementInfo ei = env.getModifiableElementInfo(wildcardRef);
210 // Type parameter test
211 // TODO: This test could probably be made cleaner
212 String classGenericSig = mi.getClassInfo().getGenericSignature();
213 String methodGenericSig = mi.getGenericSignature();
214 String typeParameter = Types.getTypeParameter(wildcardType);
215 int uRef = MJIEnv.NULL;
216 int lRef = MJIEnv.NULL;
217 if (Types.isTypeParameter(typeParameter, methodGenericSig) ||
218 Types.isTypeParameter(typeParameter, classGenericSig)) {
219 int tpRef = getTypeVariableImplObject(env, objRef, typeParameter);
220 if (wildcardType.startsWith("+")) {
222 uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
223 env.setReferenceArrayElement(uRef, 0, tpRef);
224 lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
225 } else { // wildcardType.startsWith("-")
227 lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
228 env.setReferenceArrayElement(lRef, 0, tpRef);
229 uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
233 String actualType = Types.getWildcardType(wildcardType);
234 ClassInfo uci = cli.getResolvedClassInfo(actualType);
235 if (!uci.isRegistered()) {
236 uci.registerClass(ti);
238 if (wildcardType.startsWith("+L") || wildcardType.equals("*")) {
240 uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
241 env.setReferenceArrayElement(uRef, 0, uci.getClassObjectRef());
242 lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
243 } else { // wildcardType.startsWith("-L")
245 lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
246 env.setReferenceArrayElement(lRef, 0, uci.getClassObjectRef());
249 ei.setReferenceField("upperBounds", uRef);
250 ei.setReferenceField("lowerBounds", lRef);
255 private static int getTypeVariableImplObject(MJIEnv env, int objRef, String parameterizedType) {
257 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
258 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
260 int typeVarRef = env.newObject(ci);
261 ElementInfo ei = env.getModifiableElementInfo(typeVarRef);
262 // genericDeclaration contains this java.lang.reflect.Method object
263 ei.setReferenceField("genericDeclaration", objRef);
264 ei.setReferenceField("name", env.newString(parameterizedType));
269 static int getGenericParameterTypes( MJIEnv env, int objRef, MethodInfo mi) {
270 ThreadInfo ti = env.getThreadInfo();
271 String[] argTypeNames = mi.getArgumentGenericTypeNames();
272 int[] ar = new int[argTypeNames.length];
274 String classGenericSig = mi.getClassInfo().getGenericSignature();
275 String methodGenericSig = mi.getGenericSignature();
276 for (int i = 0; i < argTypeNames.length; i++) {
277 // Change this into just the generic class type if it is a generic class
278 if (Types.isGenericSignature(argTypeNames[i])) {
279 if (Types.isArraySignature(argTypeNames[i])) {
281 ar[i] = getGenericArrayTypeImplObj(argTypeNames[i], env, objRef, mi);
283 ar[i] = getParameterizedTypeImplObj(argTypeNames[i], env, objRef, mi);
285 } else if (Types.isTypeParameter(argTypeNames[i], methodGenericSig) ||
286 Types.isTypeParameter(argTypeNames[i], classGenericSig)) {
287 if (Types.isArraySignature(argTypeNames[i])) {
289 ar[i] = getGenericArrayTypeImplObj(argTypeNames[i], env, objRef, mi);
291 ar[i] = getTypeVariableImplObject(env, objRef, argTypeNames[i]);
294 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(argTypeNames[i]);
295 if (!ci.isRegistered()) {
296 ci.registerClass(ti);
298 ar[i] = ci.getClassObjectRef();
301 int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", argTypeNames.length);
302 for (int i = 0; i < argTypeNames.length; i++) {
303 env.setReferenceArrayElement(aRef, i, ar[i]);
309 public int getGenericParameterTypes_____3Ljava_lang_reflect_Type_2 (MJIEnv env, int objRef){
310 return getGenericParameterTypes(env, objRef, getMethodInfo(env, objRef));
314 public int getGenericReturnType____Ljava_lang_reflect_Type_2 (MJIEnv env, int objRef){
315 MethodInfo mi = getMethodInfo(env, objRef);
316 ThreadInfo ti = env.getThreadInfo();
318 String genRetType = mi.getGenericReturnTypeName();
319 String classGenericSig = mi.getClassInfo().getGenericSignature();
320 String methodGenericSig = mi.getGenericSignature();
323 if (Types.isGenericSignature(genRetType)) {
324 if (Types.isArraySignature(genRetType)) {
326 retRef = getGenericArrayTypeImplObj(genRetType, env, objRef, mi);
328 retRef = getParameterizedTypeImplObj(genRetType, env, objRef, mi);
330 } else if (Types.isTypeParameter(genRetType, methodGenericSig) ||
331 Types.isTypeParameter(genRetType, classGenericSig)) {
332 if (Types.isArraySignature(genRetType)) {
334 retRef = getGenericArrayTypeImplObj(genRetType, env, objRef, mi);
336 retRef = getTypeVariableImplObject(env, objRef, genRetType);
339 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName());
340 if (!ci.isRegistered()) {
341 ci.registerClass(ti);
343 retRef = ci.getClassObjectRef();
348 // TODO: Fix for Groovy's model-checking
350 int getExceptionTypes(MJIEnv env, MethodInfo mi) {
351 ThreadInfo ti = env.getThreadInfo();
352 String[] exceptionNames = mi.getThrownExceptionClassNames();
354 if (exceptionNames == null) {
355 exceptionNames = new String[0];
358 int[] ar = new int[exceptionNames.length];
360 for (int i = 0; i < exceptionNames.length; i++) {
361 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(exceptionNames[i]);
362 if (!ci.isRegistered()) {
363 ci.registerClass(ti);
366 ar[i] = ci.getClassObjectRef();
369 int aRef = env.newObjectArray("Ljava/lang/Class;", exceptionNames.length);
370 for (int i = 0; i < exceptionNames.length; i++) {
371 env.setReferenceArrayElement(aRef, i, ar[i]);
378 public int getExceptionTypes_____3Ljava_lang_Class_2 (MJIEnv env, int objRef) {
379 return getExceptionTypes(env, getMethodInfo(env, objRef));
383 public int getDefaultValue____Ljava_lang_Object_2(MJIEnv env, int objRef) {
384 MethodInfo mi = getMethodInfo(env, objRef);
385 ClassInfo ci = mi.getClassInfo();
386 if(!ci.isInterface() || ci.getDirectInterfaceNames() == null || ci.getDirectInterfaceNames().length != 1 || !ci.getDirectInterfaceNames()[0].equals("java.lang.annotation.Annotation")) {
389 String annotationName = ci.getName();
390 AnnotationInfo ai = ci.getClassLoaderInfo().getResolvedAnnotationInfo(annotationName);
391 Object o = ai.getValue(mi.getName());
396 return env.liftNativeAnnotationValue(Types.getTypeName(mi.getReturnType()), o);
397 } catch(ClinitRequired e) {
398 env.handleClinitRequest(e.getRequiredClassInfo());
404 public int getReturnType____Ljava_lang_Class_2 (MJIEnv env, int objRef){
405 MethodInfo mi = getMethodInfo(env, objRef);
406 ThreadInfo ti = env.getThreadInfo();
408 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName());
409 if (!ci.isRegistered()) {
410 ci.registerClass(ti);
413 return ci.getClassObjectRef();
417 public int getDeclaringClass____Ljava_lang_Class_2 (MJIEnv env, int objRef){
418 MethodInfo mi = getMethodInfo(env, objRef);
419 ClassInfo ci = mi.getClassInfo();
420 // it's got to be registered, otherwise we wouldn't be able to acquire the Method object
421 return ci.getClassObjectRef();
424 static int createBoxedReturnValueObject (MJIEnv env, MethodInfo mi, DirectCallStackFrame frame) {
425 byte rt = mi.getReturnTypeCode();
426 int ret = MJIEnv.NULL;
430 if (rt == Types.T_DOUBLE) {
431 attr = frame.getLongResultAttr();
432 double v = frame.getDoubleResult();
433 ret = env.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Double"));
434 rei = env.getModifiableElementInfo(ret);
435 rei.setDoubleField("value", v);
436 } else if (rt == Types.T_FLOAT) {
437 attr = frame.getResultAttr();
438 float v = frame.getFloatResult();
439 ret = env.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Float"));
440 rei = env.getModifiableElementInfo(ret);
441 rei.setFloatField("value", v);
442 } else if (rt == Types.T_LONG) {
443 attr = frame.getLongResultAttr();
444 long v = frame.getLongResult();
445 ret = env.valueOfLong(v);
446 } else if (rt == Types.T_BYTE) {
447 attr = frame.getResultAttr();
448 int v = frame.getResult();
449 ret = env.valueOfByte((byte)v);
450 } else if (rt == Types.T_CHAR) {
451 attr = frame.getResultAttr();
452 int v = frame.getResult();
453 ret = env.valueOfCharacter((char)v);
454 } else if (rt == Types.T_SHORT) {
455 attr = frame.getResultAttr();
456 int v = frame.getResult();
457 ret = env.valueOfShort((short)v);
458 } else if (rt == Types.T_INT) {
459 attr = frame.getResultAttr();
460 int v = frame.getResult();
461 ret = env.valueOfInteger(v);
462 } else if (rt == Types.T_BOOLEAN) {
463 attr = frame.getResultAttr();
464 int v = frame.getResult();
465 ret = env.valueOfBoolean((v == 1)? true: false);
466 } else if (mi.isReferenceReturnType()){
467 attr = frame.getResultAttr();
468 ret = frame.getReferenceResult();
471 env.setReturnAttribute(attr);
475 static boolean pushUnboxedArguments (MJIEnv env, MethodInfo mi, DirectCallStackFrame frame, int argIdx, int argsRef) {
477 ClassInfo sourceClass;
478 String destTypeNames[];
479 int nArgs, passedCount, sourceRef;
480 byte sourceType, destTypes[];
482 destTypes = mi.getArgumentTypes();
483 destTypeNames = mi.getArgumentTypeNames();
484 nArgs = destTypeNames.length;
486 // according to the API docs, passing null instead of an empty array is allowed for no args
487 passedCount = (argsRef != MJIEnv.NULL) ? env.getArrayLength(argsRef) : 0;
489 if (nArgs != passedCount) {
490 env.throwException(IllegalArgumentException.class.getName(), "Wrong number of arguments passed. Actual = " + passedCount + ". Expected = " + nArgs);
494 for (int i = 0; i < nArgs; i++) {
495 sourceRef = env.getReferenceArrayElement(argsRef, i);
497 // we have to handle null references explicitly
498 if (sourceRef == MJIEnv.NULL) {
499 if ((destTypes[i] != Types.T_REFERENCE) && (destTypes[i] != Types.T_ARRAY)) {
500 env.throwException(IllegalArgumentException.class.getName(), "Wrong argument type at index " + i + ". Actual = (null). Expected = " + destTypeNames[i]);
504 frame.pushRef(MJIEnv.NULL);
508 source = env.getElementInfo(sourceRef);
509 sourceClass = source.getClassInfo();
510 sourceType = getSourceType( sourceClass, destTypes[i], destTypeNames[i]);
512 Object attr = env.getElementInfo(argsRef).getFields().getFieldAttr(i);
513 if ((argIdx = pushArg( argIdx, frame, source, sourceType, destTypes[i], attr)) < 0 ){
514 env.throwException(IllegalArgumentException.class.getName(), "Wrong argument type at index " + i + ". Source Class = " + sourceClass.getName() + ". Dest Class = " + destTypeNames[i]);
522 // this returns the primitive type in case we have to unbox, and otherwise checks reference type compatibility
523 private static byte getSourceType (ClassInfo ciArgVal, byte destType, String destTypeName){
526 case Types.T_BOOLEAN:
534 return Types.getUnboxedType(ciArgVal.getName());
537 case Types.T_REFERENCE: // check if the source type is assignment compatible with the destType
538 if (ciArgVal.isInstanceOf(destTypeName)){
546 // do the proper type conversion - Java is pretty forgiving here and does
547 // not throw exceptions upon value truncation
548 private static int pushArg( int argIdx, DirectCallStackFrame frame, ElementInfo eiArg, byte srcType, byte destType, Object attr){
552 double v = eiArg.getDoubleField("value");
553 if (destType == Types.T_DOUBLE){
554 return frame.setDoubleArgument( argIdx, v, attr);
558 case Types.T_FLOAT: // covers float, double
560 float v = eiArg.getFloatField("value");
563 return frame.setFloatArgument( argIdx, v, attr);
565 return frame.setDoubleArgument( argIdx, v, attr);
571 long v = eiArg.getLongField("value");
574 return frame.setLongArgument(argIdx, v, attr);
576 return frame.setFloatArgument(argIdx, v, attr);
578 return frame.setDoubleArgument( argIdx, v, attr);
584 int v = eiArg.getIntField("value");
587 return frame.setArgument( argIdx, v, attr);
589 return frame.setLongArgument( argIdx, v, attr);
591 return frame.setFloatArgument(argIdx, v, attr);
593 return frame.setDoubleArgument( argIdx, v, attr);
599 int v = eiArg.getShortField("value");
603 return frame.setArgument( argIdx, v, attr);
605 return frame.setLongArgument( argIdx, v, attr);
607 return frame.setFloatArgument(argIdx, v, attr);
609 return frame.setDoubleArgument( argIdx, v, attr);
615 byte v = eiArg.getByteField("value");
620 return frame.setArgument( argIdx, v, attr);
622 return frame.setLongArgument( argIdx, v, attr);
624 return frame.setFloatArgument(argIdx, v, attr);
626 return frame.setDoubleArgument( argIdx, v, attr);
632 char v = eiArg.getCharField("value");
636 return frame.setArgument( argIdx, v, attr);
638 return frame.setLongArgument( argIdx, v, attr);
640 return frame.setFloatArgument(argIdx, v, attr);
642 return frame.setDoubleArgument( argIdx, v, attr);
646 case Types.T_BOOLEAN:
648 boolean v = eiArg.getBooleanField("value");
649 if (destType == Types.T_BOOLEAN){
650 return frame.setArgument( argIdx, v ? 1 : 0, attr);
656 int ref = eiArg.getObjectRef();
657 if (destType == Types.T_ARRAY){
658 return frame.setReferenceArgument( argIdx, ref, attr);
662 case Types.T_REFERENCE:
664 int ref = eiArg.getObjectRef();
665 if (destType == Types.T_REFERENCE){
666 return frame.setReferenceArgument( argIdx, ref, attr);
677 public int invoke__Ljava_lang_Object_2_3Ljava_lang_Object_2__Ljava_lang_Object_2 (MJIEnv env, int mthRef, int objRef, int argsRef) {
678 ThreadInfo ti = env.getThreadInfo();
679 MethodInfo miCallee = getMethodInfo(env, mthRef);
680 ClassInfo calleeClass = miCallee.getClassInfo();
681 DirectCallStackFrame frame = ti.getReturnedDirectCall();
683 if (frame == null){ // first time
685 //--- check the instance we are calling on
686 if (!miCallee.isStatic()) {
687 if (objRef == MJIEnv.NULL){
688 env.throwException("java.lang.NullPointerException");
692 ElementInfo eiObj = ti.getElementInfo(objRef);
693 ClassInfo objClass = eiObj.getClassInfo();
695 if (!objClass.isInstanceOf(calleeClass)) {
696 env.throwException(IllegalArgumentException.class.getName(), "Object is not an instance of declaring class. Actual = " + objClass + ". Expected = " + calleeClass);
702 //--- check accessibility
703 ElementInfo eiMth = ti.getElementInfo(mthRef);
704 if (! (Boolean) eiMth.getFieldValueObject("isAccessible")) {
705 StackFrame caller = ti.getTopFrame().getPrevious();
706 ClassInfo callerClass = caller.getClassInfo();
708 if (callerClass != calleeClass) {
709 env.throwException(IllegalAccessException.class.getName(), "Class " + callerClass.getName() +
710 " can not access a member of class " + calleeClass.getName()
711 + " with modifiers \"" + Modifier.toString(miCallee.getModifiers()));
716 //--- push the direct call
717 frame = miCallee.createDirectCallStackFrame(ti, 0);
718 frame.setReflection();
721 if (!miCallee.isStatic()) {
722 frame.setReferenceArgument( argOffset++, objRef, null);
724 if (!pushUnboxedArguments( env, miCallee, frame, argOffset, argsRef)) {
725 // we've got a IllegalArgumentException
731 //--- check for and push required clinits
732 if (miCallee.isStatic()){
733 calleeClass.initializeClass(ti);
736 return MJIEnv.NULL; // reexecute
738 } else { // we have returned from the direct call
739 return createBoxedReturnValueObject( env, miCallee, frame);
744 // this one has to collect annotations upwards in the inheritance chain
745 static int getAnnotations (MJIEnv env, MethodInfo mi){
746 String mname = mi.getName();
747 String msig = mi.genericSignature;
748 ArrayList<AnnotationInfo> aiList = new ArrayList<AnnotationInfo>();
750 // our own annotations
751 ClassInfo ci = mi.getClassInfo();
752 for (AnnotationInfo ai : mi.getAnnotations()) {
756 // our superclass annotations
757 for (ci = ci.getSuperClass(); ci != null; ci = ci.getSuperClass()){
758 mi = ci.getMethod(mname, msig, false);
760 for (AnnotationInfo ai: mi.getAnnotations()){
767 return env.newAnnotationProxies(aiList.toArray(new AnnotationInfo[aiList.size()]));
768 } catch (ClinitRequired x){
769 env.handleClinitRequest(x.getRequiredClassInfo());
775 public int getAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int mthRef){
776 return getAnnotations( env, getMethodInfo(env,mthRef));
779 // the following ones consist of a package default implementation that is shared with
780 // the constructor peer, and a public model method
781 static int getAnnotation (MJIEnv env, MethodInfo mi, int annotationClsRef){
782 ClassInfo aci = env.getReferredClassInfo(annotationClsRef);
784 AnnotationInfo ai = mi.getAnnotation(aci.getName());
786 ClassInfo aciProxy = aci.getAnnotationProxy();
788 return env.newAnnotationProxy(aciProxy, ai);
789 } catch (ClinitRequired x){
790 env.handleClinitRequest(x.getRequiredClassInfo());
799 public int getAnnotation__Ljava_lang_Class_2__Ljava_lang_annotation_Annotation_2 (MJIEnv env, int mthRef, int annotationClsRef) {
800 return getAnnotation(env, getMethodInfo(env,mthRef), annotationClsRef);
803 static int getDeclaredAnnotations (MJIEnv env, MethodInfo mi){
804 AnnotationInfo[] ai = mi.getAnnotations();
807 return env.newAnnotationProxies(ai);
808 } catch (ClinitRequired x){
809 env.handleClinitRequest(x.getRequiredClassInfo());
815 public int getDeclaredAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int mthRef){
816 return getDeclaredAnnotations( env, getMethodInfo(env,mthRef));
819 static int getParameterAnnotations (MJIEnv env, MethodInfo mi){
820 AnnotationInfo[][] pa = mi.getParameterAnnotations();
821 // this should always return an array object, even if the method has no arguments
824 int paRef = env.newObjectArray("[Ljava/lang/annotation/Annotation;", pa.length);
826 for (int i=0; i<pa.length; i++){
827 int eRef = env.newAnnotationProxies(pa[i]);
828 env.setReferenceArrayElement(paRef, i, eRef);
833 } catch (ClinitRequired x){ // be prepared that we might have to initialize respective annotation classes
834 env.handleClinitRequest(x.getRequiredClassInfo());
840 public int getParameterAnnotations_____3_3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int mthRef){
841 return getParameterAnnotations( env, getMethodInfo(env,mthRef));
845 public int toString____Ljava_lang_String_2 (MJIEnv env, int objRef){
846 StringBuilder sb = new StringBuilder();
848 MethodInfo mi = getMethodInfo(env, objRef);
850 sb.append(Modifier.toString(mi.getModifiers()));
853 sb.append(mi.getReturnTypeName());
856 sb.append(mi.getClassName());
859 sb.append(mi.getName());
863 String[] at = mi.getArgumentTypeNames();
864 for (int i=0; i<at.length; i++){
865 if (i>0) sb.append(',');
871 int sref = env.newString(sb.toString());
876 public boolean equals__Ljava_lang_Object_2__Z (MJIEnv env, int objRef, int mthRef){
877 ElementInfo ei = env.getElementInfo(mthRef);
878 ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo(JPF_java_lang_Class.METHOD_CLASSNAME);
880 if (ei.getClassInfo() == ci){
881 MethodInfo mi1 = getMethodInfo(env, objRef);
882 MethodInfo mi2 = getMethodInfo(env, mthRef);
883 if (mi1.getClassInfo() == mi2.getClassInfo()){
884 if (mi1.getName().equals(mi2.getName())){
885 if (mi1.getReturnType().equals(mi2.getReturnType())){
886 byte[] params1 = mi1.getArgumentTypes();
887 byte[] params2 = mi2.getArgumentTypes();
888 if (params1.length == params2.length){
889 for (int i = 0; i < params1.length; i++){
890 if (params1[i] != params2[i]){
904 public int hashCode____I (MJIEnv env, int objRef){
905 MethodInfo mi = getMethodInfo(env, objRef);
906 return mi.getClassName().hashCode() ^ mi.getName().hashCode();