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);
131 int paramTypeRef = getParameterizedTypeImplObj(clsSig, env, objRef, mi);
132 ei.setReferenceField("genericComponentType", paramTypeRef);
137 private static int getParameterizedTypeImplObj(String signature, MJIEnv env, int objRef, MethodInfo mi) {
139 ThreadInfo ti = env.getThreadInfo();
140 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
141 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl");
142 // Create a new object of type ParameterizedTypeImpl
143 int paramTypeRef = env.newObject(ci);
144 ElementInfo ei = env.getModifiableElementInfo(paramTypeRef);
145 // Get field information and fill out the fields
147 String className = Types.getGenericClassName(signature);
148 ClassInfo gci = cli.getResolvedClassInfo(className);
149 if (!gci.isRegistered()) {
150 gci.registerClass(ti);
152 ei.setReferenceField("rawType", gci.getClassObjectRef());
154 // actualTypeArguments
155 String[] parameterizedTypes = Types.getParameterizedTypes(signature);
156 int[] types = new int[parameterizedTypes.length];
157 String classGenericSig = mi.getClassInfo().getGenericSignature();
158 String methodGenericSig = mi.getGenericSignature();
159 for(int j = 0; j < parameterizedTypes.length; j++) {
160 if (Types.isTypeParameter(parameterizedTypes[j], methodGenericSig) ||
161 Types.isTypeParameter(parameterizedTypes[j], classGenericSig)) {
162 types[j] = getTypeVariableImplObject(env, objRef, parameterizedTypes[j]);
163 } else if (Types.isWildcardType(parameterizedTypes[j])) {
164 types[j] = getWildcardTypeImplObject(env, objRef, parameterizedTypes[j], mi);
165 } else if (Types.isParameterizedType(parameterizedTypes[j])) {
167 types[j] = getParameterizedTypeImplObj(parameterizedTypes[j], env, objRef, mi);
169 ClassInfo pci = cli.getResolvedClassInfo(parameterizedTypes[j]);
170 if (!pci.isRegistered()) {
171 pci.registerClass(ti);
173 types[j] = pci.getClassObjectRef();
176 int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", parameterizedTypes.length);
177 // Set references for every array element
178 for (int j = 0; j < parameterizedTypes.length; j++) {
179 env.setReferenceArrayElement(aRef, j, types[j]);
181 ei.setReferenceField("actualTypeArguments", aRef);
184 String ownerType = Types.getOwnerClassName(signature);
185 if (ownerType != null) {
186 ClassInfo oci = ClassLoaderInfo.getCurrentResolvedClassInfo(ownerType);
187 if (!oci.isRegistered()) {
188 oci.registerClass(ti);
190 ei.setReferenceField("ownerType", oci.getClassObjectRef());
192 ei.setReferenceField("ownerType", MJIEnv.NULL);
198 private static int getWildcardTypeImplObject(MJIEnv env, int objRef, String wildcardType, MethodInfo mi) {
199 ThreadInfo ti = env.getThreadInfo();
200 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
201 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.WildcardTypeImpl");
203 int wildcardRef = env.newObject(ci);
204 ElementInfo ei = env.getModifiableElementInfo(wildcardRef);
205 // Type parameter test
206 // TODO: This test could probably be made cleaner
207 String classGenericSig = mi.getClassInfo().getGenericSignature();
208 String methodGenericSig = mi.getGenericSignature();
209 String typeParameter = Types.getTypeParameter(wildcardType);
210 int uRef = MJIEnv.NULL;
211 int lRef = MJIEnv.NULL;
212 if (Types.isTypeParameter(typeParameter, methodGenericSig) ||
213 Types.isTypeParameter(typeParameter, classGenericSig)) {
214 int tpRef = getTypeVariableImplObject(env, objRef, typeParameter);
215 if (wildcardType.startsWith("+")) {
217 uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
218 env.setReferenceArrayElement(uRef, 0, tpRef);
219 lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
220 } else { // wildcardType.startsWith("-")
222 lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
223 env.setReferenceArrayElement(lRef, 0, tpRef);
224 uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
228 String actualType = Types.getWildcardType(wildcardType);
229 ClassInfo uci = cli.getResolvedClassInfo(actualType);
230 if (!uci.isRegistered()) {
231 uci.registerClass(ti);
233 if (wildcardType.startsWith("+L") || wildcardType.equals("*")) {
235 uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
236 env.setReferenceArrayElement(uRef, 0, uci.getClassObjectRef());
237 lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
238 } else { // wildcardType.startsWith("-L")
240 lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
241 env.setReferenceArrayElement(lRef, 0, uci.getClassObjectRef());
244 ei.setReferenceField("upperBounds", uRef);
245 ei.setReferenceField("lowerBounds", lRef);
250 private static int getTypeVariableImplObject(MJIEnv env, int objRef, String parameterizedType) {
252 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
253 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
255 int typeVarRef = env.newObject(ci);
256 ElementInfo ei = env.getModifiableElementInfo(typeVarRef);
257 // genericDeclaration contains this java.lang.reflect.Method object
258 ei.setReferenceField("genericDeclaration", objRef);
259 ei.setReferenceField("name", env.newString(parameterizedType));
264 static int getGenericParameterTypes( MJIEnv env, int objRef, MethodInfo mi) {
265 ThreadInfo ti = env.getThreadInfo();
266 String[] argTypeNames = mi.getArgumentGenericTypeNames();
267 int[] ar = new int[argTypeNames.length];
269 for (int i = 0; i < argTypeNames.length; i++) {
270 // Change this into just the generic class type if it is a generic class
271 if (Types.isGenericSignature(argTypeNames[i])) {
272 if (Types.isArraySignature(argTypeNames[i])) {
274 ar[i] = getGenericArrayTypeImplObj(argTypeNames[i], env, objRef, mi);
276 ar[i] = getParameterizedTypeImplObj(argTypeNames[i], env, objRef, mi);
279 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(argTypeNames[i]);
280 if (!ci.isRegistered()) {
281 ci.registerClass(ti);
283 ar[i] = ci.getClassObjectRef();
286 int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", argTypeNames.length);
287 for (int i = 0; i < argTypeNames.length; i++) {
288 env.setReferenceArrayElement(aRef, i, ar[i]);
294 public int getGenericParameterTypes_____3Ljava_lang_reflect_Type_2 (MJIEnv env, int objRef){
295 return getGenericParameterTypes(env, objRef, getMethodInfo(env, objRef));
299 public int getGenericReturnType____Ljava_lang_reflect_Type_2 (MJIEnv env, int objRef){
300 MethodInfo mi = getMethodInfo(env, objRef);
301 ThreadInfo ti = env.getThreadInfo();
304 if (Types.isGenericSignature(mi.getGenericReturnTypeName())) {
305 if (Types.isArraySignature(mi.getGenericReturnTypeName())) {
307 retRef = getGenericArrayTypeImplObj(mi.getGenericReturnTypeName(), env, objRef, mi);
309 retRef = getParameterizedTypeImplObj(mi.getGenericReturnTypeName(), env, objRef, mi);
312 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName());
313 if (!ci.isRegistered()) {
314 ci.registerClass(ti);
316 retRef = ci.getClassObjectRef();
321 // TODO: Fix for Groovy's model-checking
323 int getExceptionTypes(MJIEnv env, MethodInfo mi) {
324 ThreadInfo ti = env.getThreadInfo();
325 String[] exceptionNames = mi.getThrownExceptionClassNames();
327 if (exceptionNames == null) {
328 exceptionNames = new String[0];
331 int[] ar = new int[exceptionNames.length];
333 for (int i = 0; i < exceptionNames.length; i++) {
334 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(exceptionNames[i]);
335 if (!ci.isRegistered()) {
336 ci.registerClass(ti);
339 ar[i] = ci.getClassObjectRef();
342 int aRef = env.newObjectArray("Ljava/lang/Class;", exceptionNames.length);
343 for (int i = 0; i < exceptionNames.length; i++) {
344 env.setReferenceArrayElement(aRef, i, ar[i]);
351 public int getExceptionTypes_____3Ljava_lang_Class_2 (MJIEnv env, int objRef) {
352 return getExceptionTypes(env, getMethodInfo(env, objRef));
356 public int getDefaultValue____Ljava_lang_Object_2(MJIEnv env, int objRef) {
357 MethodInfo mi = getMethodInfo(env, objRef);
358 ClassInfo ci = mi.getClassInfo();
359 if(!ci.isInterface() || ci.getDirectInterfaceNames() == null || ci.getDirectInterfaceNames().length != 1 || !ci.getDirectInterfaceNames()[0].equals("java.lang.annotation.Annotation")) {
362 String annotationName = ci.getName();
363 AnnotationInfo ai = ci.getClassLoaderInfo().getResolvedAnnotationInfo(annotationName);
364 Object o = ai.getValue(mi.getName());
369 return env.liftNativeAnnotationValue(Types.getTypeName(mi.getReturnType()), o);
370 } catch(ClinitRequired e) {
371 env.handleClinitRequest(e.getRequiredClassInfo());
377 public int getReturnType____Ljava_lang_Class_2 (MJIEnv env, int objRef){
378 MethodInfo mi = getMethodInfo(env, objRef);
379 ThreadInfo ti = env.getThreadInfo();
381 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName());
382 if (!ci.isRegistered()) {
383 ci.registerClass(ti);
386 return ci.getClassObjectRef();
390 public int getDeclaringClass____Ljava_lang_Class_2 (MJIEnv env, int objRef){
391 MethodInfo mi = getMethodInfo(env, objRef);
392 ClassInfo ci = mi.getClassInfo();
393 // it's got to be registered, otherwise we wouldn't be able to acquire the Method object
394 return ci.getClassObjectRef();
397 static int createBoxedReturnValueObject (MJIEnv env, MethodInfo mi, DirectCallStackFrame frame) {
398 byte rt = mi.getReturnTypeCode();
399 int ret = MJIEnv.NULL;
403 if (rt == Types.T_DOUBLE) {
404 attr = frame.getLongResultAttr();
405 double v = frame.getDoubleResult();
406 ret = env.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Double"));
407 rei = env.getModifiableElementInfo(ret);
408 rei.setDoubleField("value", v);
409 } else if (rt == Types.T_FLOAT) {
410 attr = frame.getResultAttr();
411 float v = frame.getFloatResult();
412 ret = env.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Float"));
413 rei = env.getModifiableElementInfo(ret);
414 rei.setFloatField("value", v);
415 } else if (rt == Types.T_LONG) {
416 attr = frame.getLongResultAttr();
417 long v = frame.getLongResult();
418 ret = env.valueOfLong(v);
419 } else if (rt == Types.T_BYTE) {
420 attr = frame.getResultAttr();
421 int v = frame.getResult();
422 ret = env.valueOfByte((byte)v);
423 } else if (rt == Types.T_CHAR) {
424 attr = frame.getResultAttr();
425 int v = frame.getResult();
426 ret = env.valueOfCharacter((char)v);
427 } else if (rt == Types.T_SHORT) {
428 attr = frame.getResultAttr();
429 int v = frame.getResult();
430 ret = env.valueOfShort((short)v);
431 } else if (rt == Types.T_INT) {
432 attr = frame.getResultAttr();
433 int v = frame.getResult();
434 ret = env.valueOfInteger(v);
435 } else if (rt == Types.T_BOOLEAN) {
436 attr = frame.getResultAttr();
437 int v = frame.getResult();
438 ret = env.valueOfBoolean((v == 1)? true: false);
439 } else if (mi.isReferenceReturnType()){
440 attr = frame.getResultAttr();
441 ret = frame.getReferenceResult();
444 env.setReturnAttribute(attr);
448 static boolean pushUnboxedArguments (MJIEnv env, MethodInfo mi, DirectCallStackFrame frame, int argIdx, int argsRef) {
450 ClassInfo sourceClass;
451 String destTypeNames[];
452 int nArgs, passedCount, sourceRef;
453 byte sourceType, destTypes[];
455 destTypes = mi.getArgumentTypes();
456 destTypeNames = mi.getArgumentTypeNames();
457 nArgs = destTypeNames.length;
459 // according to the API docs, passing null instead of an empty array is allowed for no args
460 passedCount = (argsRef != MJIEnv.NULL) ? env.getArrayLength(argsRef) : 0;
462 if (nArgs != passedCount) {
463 env.throwException(IllegalArgumentException.class.getName(), "Wrong number of arguments passed. Actual = " + passedCount + ". Expected = " + nArgs);
467 for (int i = 0; i < nArgs; i++) {
468 sourceRef = env.getReferenceArrayElement(argsRef, i);
470 // we have to handle null references explicitly
471 if (sourceRef == MJIEnv.NULL) {
472 if ((destTypes[i] != Types.T_REFERENCE) && (destTypes[i] != Types.T_ARRAY)) {
473 env.throwException(IllegalArgumentException.class.getName(), "Wrong argument type at index " + i + ". Actual = (null). Expected = " + destTypeNames[i]);
477 frame.pushRef(MJIEnv.NULL);
481 source = env.getElementInfo(sourceRef);
482 sourceClass = source.getClassInfo();
483 sourceType = getSourceType( sourceClass, destTypes[i], destTypeNames[i]);
485 Object attr = env.getElementInfo(argsRef).getFields().getFieldAttr(i);
486 if ((argIdx = pushArg( argIdx, frame, source, sourceType, destTypes[i], attr)) < 0 ){
487 env.throwException(IllegalArgumentException.class.getName(), "Wrong argument type at index " + i + ". Source Class = " + sourceClass.getName() + ". Dest Class = " + destTypeNames[i]);
495 // this returns the primitive type in case we have to unbox, and otherwise checks reference type compatibility
496 private static byte getSourceType (ClassInfo ciArgVal, byte destType, String destTypeName){
499 case Types.T_BOOLEAN:
507 return Types.getUnboxedType(ciArgVal.getName());
510 case Types.T_REFERENCE: // check if the source type is assignment compatible with the destType
511 if (ciArgVal.isInstanceOf(destTypeName)){
519 // do the proper type conversion - Java is pretty forgiving here and does
520 // not throw exceptions upon value truncation
521 private static int pushArg( int argIdx, DirectCallStackFrame frame, ElementInfo eiArg, byte srcType, byte destType, Object attr){
525 double v = eiArg.getDoubleField("value");
526 if (destType == Types.T_DOUBLE){
527 return frame.setDoubleArgument( argIdx, v, attr);
531 case Types.T_FLOAT: // covers float, double
533 float v = eiArg.getFloatField("value");
536 return frame.setFloatArgument( argIdx, v, attr);
538 return frame.setDoubleArgument( argIdx, v, attr);
544 long v = eiArg.getLongField("value");
547 return frame.setLongArgument(argIdx, v, attr);
549 return frame.setFloatArgument(argIdx, v, attr);
551 return frame.setDoubleArgument( argIdx, v, attr);
557 int v = eiArg.getIntField("value");
560 return frame.setArgument( argIdx, v, attr);
562 return frame.setLongArgument( argIdx, v, attr);
564 return frame.setFloatArgument(argIdx, v, attr);
566 return frame.setDoubleArgument( argIdx, v, attr);
572 int v = eiArg.getShortField("value");
576 return frame.setArgument( argIdx, v, attr);
578 return frame.setLongArgument( argIdx, v, attr);
580 return frame.setFloatArgument(argIdx, v, attr);
582 return frame.setDoubleArgument( argIdx, v, attr);
588 byte v = eiArg.getByteField("value");
593 return frame.setArgument( argIdx, v, attr);
595 return frame.setLongArgument( argIdx, v, attr);
597 return frame.setFloatArgument(argIdx, v, attr);
599 return frame.setDoubleArgument( argIdx, v, attr);
605 char v = eiArg.getCharField("value");
609 return frame.setArgument( argIdx, v, attr);
611 return frame.setLongArgument( argIdx, v, attr);
613 return frame.setFloatArgument(argIdx, v, attr);
615 return frame.setDoubleArgument( argIdx, v, attr);
619 case Types.T_BOOLEAN:
621 boolean v = eiArg.getBooleanField("value");
622 if (destType == Types.T_BOOLEAN){
623 return frame.setArgument( argIdx, v ? 1 : 0, attr);
629 int ref = eiArg.getObjectRef();
630 if (destType == Types.T_ARRAY){
631 return frame.setReferenceArgument( argIdx, ref, attr);
635 case Types.T_REFERENCE:
637 int ref = eiArg.getObjectRef();
638 if (destType == Types.T_REFERENCE){
639 return frame.setReferenceArgument( argIdx, ref, attr);
650 public int invoke__Ljava_lang_Object_2_3Ljava_lang_Object_2__Ljava_lang_Object_2 (MJIEnv env, int mthRef, int objRef, int argsRef) {
651 ThreadInfo ti = env.getThreadInfo();
652 MethodInfo miCallee = getMethodInfo(env, mthRef);
653 ClassInfo calleeClass = miCallee.getClassInfo();
654 DirectCallStackFrame frame = ti.getReturnedDirectCall();
656 if (frame == null){ // first time
658 //--- check the instance we are calling on
659 if (!miCallee.isStatic()) {
660 if (objRef == MJIEnv.NULL){
661 env.throwException("java.lang.NullPointerException");
665 ElementInfo eiObj = ti.getElementInfo(objRef);
666 ClassInfo objClass = eiObj.getClassInfo();
668 if (!objClass.isInstanceOf(calleeClass)) {
669 env.throwException(IllegalArgumentException.class.getName(), "Object is not an instance of declaring class. Actual = " + objClass + ". Expected = " + calleeClass);
675 //--- check accessibility
676 ElementInfo eiMth = ti.getElementInfo(mthRef);
677 if (! (Boolean) eiMth.getFieldValueObject("isAccessible")) {
678 StackFrame caller = ti.getTopFrame().getPrevious();
679 ClassInfo callerClass = caller.getClassInfo();
681 if (callerClass != calleeClass) {
682 env.throwException(IllegalAccessException.class.getName(), "Class " + callerClass.getName() +
683 " can not access a member of class " + calleeClass.getName()
684 + " with modifiers \"" + Modifier.toString(miCallee.getModifiers()));
689 //--- push the direct call
690 frame = miCallee.createDirectCallStackFrame(ti, 0);
691 frame.setReflection();
694 if (!miCallee.isStatic()) {
695 frame.setReferenceArgument( argOffset++, objRef, null);
697 if (!pushUnboxedArguments( env, miCallee, frame, argOffset, argsRef)) {
698 // we've got a IllegalArgumentException
704 //--- check for and push required clinits
705 if (miCallee.isStatic()){
706 calleeClass.initializeClass(ti);
709 return MJIEnv.NULL; // reexecute
711 } else { // we have returned from the direct call
712 return createBoxedReturnValueObject( env, miCallee, frame);
717 // this one has to collect annotations upwards in the inheritance chain
718 static int getAnnotations (MJIEnv env, MethodInfo mi){
719 String mname = mi.getName();
720 String msig = mi.genericSignature;
721 ArrayList<AnnotationInfo> aiList = new ArrayList<AnnotationInfo>();
723 // our own annotations
724 ClassInfo ci = mi.getClassInfo();
725 for (AnnotationInfo ai : mi.getAnnotations()) {
729 // our superclass annotations
730 for (ci = ci.getSuperClass(); ci != null; ci = ci.getSuperClass()){
731 mi = ci.getMethod(mname, msig, false);
733 for (AnnotationInfo ai: mi.getAnnotations()){
740 return env.newAnnotationProxies(aiList.toArray(new AnnotationInfo[aiList.size()]));
741 } catch (ClinitRequired x){
742 env.handleClinitRequest(x.getRequiredClassInfo());
748 public int getAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int mthRef){
749 return getAnnotations( env, getMethodInfo(env,mthRef));
752 // the following ones consist of a package default implementation that is shared with
753 // the constructor peer, and a public model method
754 static int getAnnotation (MJIEnv env, MethodInfo mi, int annotationClsRef){
755 ClassInfo aci = env.getReferredClassInfo(annotationClsRef);
757 AnnotationInfo ai = mi.getAnnotation(aci.getName());
759 ClassInfo aciProxy = aci.getAnnotationProxy();
761 return env.newAnnotationProxy(aciProxy, ai);
762 } catch (ClinitRequired x){
763 env.handleClinitRequest(x.getRequiredClassInfo());
772 public int getAnnotation__Ljava_lang_Class_2__Ljava_lang_annotation_Annotation_2 (MJIEnv env, int mthRef, int annotationClsRef) {
773 return getAnnotation(env, getMethodInfo(env,mthRef), annotationClsRef);
776 static int getDeclaredAnnotations (MJIEnv env, MethodInfo mi){
777 AnnotationInfo[] ai = mi.getAnnotations();
780 return env.newAnnotationProxies(ai);
781 } catch (ClinitRequired x){
782 env.handleClinitRequest(x.getRequiredClassInfo());
788 public int getDeclaredAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int mthRef){
789 return getDeclaredAnnotations( env, getMethodInfo(env,mthRef));
792 static int getParameterAnnotations (MJIEnv env, MethodInfo mi){
793 AnnotationInfo[][] pa = mi.getParameterAnnotations();
794 // this should always return an array object, even if the method has no arguments
797 int paRef = env.newObjectArray("[Ljava/lang/annotation/Annotation;", pa.length);
799 for (int i=0; i<pa.length; i++){
800 int eRef = env.newAnnotationProxies(pa[i]);
801 env.setReferenceArrayElement(paRef, i, eRef);
806 } catch (ClinitRequired x){ // be prepared that we might have to initialize respective annotation classes
807 env.handleClinitRequest(x.getRequiredClassInfo());
813 public int getParameterAnnotations_____3_3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int mthRef){
814 return getParameterAnnotations( env, getMethodInfo(env,mthRef));
818 public int toString____Ljava_lang_String_2 (MJIEnv env, int objRef){
819 StringBuilder sb = new StringBuilder();
821 MethodInfo mi = getMethodInfo(env, objRef);
823 sb.append(Modifier.toString(mi.getModifiers()));
826 sb.append(mi.getReturnTypeName());
829 sb.append(mi.getClassName());
832 sb.append(mi.getName());
836 String[] at = mi.getArgumentTypeNames();
837 for (int i=0; i<at.length; i++){
838 if (i>0) sb.append(',');
844 int sref = env.newString(sb.toString());
849 public boolean equals__Ljava_lang_Object_2__Z (MJIEnv env, int objRef, int mthRef){
850 ElementInfo ei = env.getElementInfo(mthRef);
851 ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo(JPF_java_lang_Class.METHOD_CLASSNAME);
853 if (ei.getClassInfo() == ci){
854 MethodInfo mi1 = getMethodInfo(env, objRef);
855 MethodInfo mi2 = getMethodInfo(env, mthRef);
856 if (mi1.getClassInfo() == mi2.getClassInfo()){
857 if (mi1.getName().equals(mi2.getName())){
858 if (mi1.getReturnType().equals(mi2.getReturnType())){
859 byte[] params1 = mi1.getArgumentTypes();
860 byte[] params2 = mi2.getArgumentTypes();
861 if (params1.length == params2.length){
862 for (int i = 0; i < params1.length; i++){
863 if (params1[i] != params2[i]){
877 public int hashCode____I (MJIEnv env, int objRef){
878 MethodInfo mi = getMethodInfo(env, objRef);
879 return mi.getClassName().hashCode() ^ mi.getName().hashCode();