Fixing the method getGenericParameterTypes to include parameterized object such as...
authorRahmadi Trimananda <rtrimana@uci.edu>
Fri, 21 Jun 2019 00:52:49 +0000 (17:52 -0700)
committerRahmadi Trimananda <rtrimana@uci.edu>
Fri, 21 Jun 2019 00:52:49 +0000 (17:52 -0700)
examples/Empty.groovy
examples/Reflection.java
src/main/gov/nasa/jpf/vm/MethodInfo.java
src/main/gov/nasa/jpf/vm/Types.java
src/peers/gov/nasa/jpf/vm/JPF_java_lang_Class.java
src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java

index 93c4cc6..55d02fe 100644 (file)
@@ -22,7 +22,7 @@ class Empty {
 
                //Empty emp = new Empty();
                //int result = emp.installed();
-               println result;
+               //println result;
                //println "Test"
        }       
 }
index f2bff8a..538bcd1 100644 (file)
@@ -43,7 +43,14 @@ public class Reflection {
    public static void main(String[] args) {
 
       Method[] methods = SampleClass.class.getMethods();
-      Type[] parameters = methods[3].getGenericParameterTypes();
+      //  Method[] methods = Class.class.getMethods();
+        Method method = null;
+        for(Method meth : methods) {
+            if (meth.getName().equals("setSampleField")) {
+                method = meth;
+            }
+        }
+        Type[] parameters = method.getGenericParameterTypes();
       //Type[] parameters = methods[0].getGenericParameterTypes();
       for (int i = 0; i < parameters.length; i++) {
          System.out.println(parameters[i]);
@@ -55,7 +62,7 @@ public class Reflection {
  
       }
       System.out.println();*/
-      TypeVariable[] typeParameters = Generic.class.getTypeParameters();
+      /*TypeVariable[] typeParameters = Generic.class.getTypeParameters();
       //TypeVariable[] typeParameters = SampleClass.class.getTypeParameters();
       for(TypeVariable typeVar: typeParameters){
          System.out.println(typeVar);   
@@ -70,7 +77,7 @@ public class Reflection {
       System.out.println();
       Type returnType = methods[0].getGenericReturnType();
       System.out.println(returnType);
-         
+         */
    }
 }
 
index 7a1d48d..4176f68 100644 (file)
@@ -509,7 +509,9 @@ public class MethodInfo extends InfoObject implements GenericSignatureHolder  {
     // TODO: in the class file.
     if (genericSignature == null || genericSignature.equals("") || genericSignature.contains("<*>"))
       return getArgumentTypeNames();
-    return Types.getArgumentTypeNames(genericSignature);
+    // We need to first find the start of the method parameters in the signature
+    String methodParameters = genericSignature.substring(genericSignature.indexOf('('));
+    return Types.getArgumentTypeNames(methodParameters);
   }
 
   public int getArgumentsSize () {
index 16ee295..6c34925 100644 (file)
@@ -1205,7 +1205,7 @@ public class Types {
   }
 
   // TODO: Fix for Groovy's model-checking
-  public static String[] getParameterizedTypesFromArgumentTypeNames(String signature) {
+  public static String[] getParameterizedTypes(String signature) {
     int pos = signature.indexOf('<', 0);
     if (pos == -1)
       return new String[0];
@@ -1251,5 +1251,12 @@ public class Types {
     int opening = signature.indexOf('<');
     return (opening != -1);
   }
+
+  public static boolean isTypeParameter(String parameterizedType, String signature) {
+    if (signature == null || signature.equals(""))
+      return false;
+    String typeParamSig = parameterizedType.concat(":");
+    return signature.contains(typeParamSig);
+  }
   // TODO: Fix for Groovy's model-checking
 }
index 8ace896..10d63c7 100644 (file)
@@ -34,9 +34,7 @@ public class JPF_java_lang_Class extends NativePeer {
   static final String FIELD_CLASSNAME = "java.lang.reflect.Field";
   static final String METHOD_CLASSNAME = "java.lang.reflect.Method";
   static final String CONSTRUCTOR_CLASSNAME = "java.lang.reflect.Constructor";
-  // TODO: Fix for Groovy's model-checking
-  static final String TYPEVARIABLE_CLASSNAME = "java.lang.reflect.TypeVariable";
-  
+
   public static boolean init (Config conf){
     // we create Method and Constructor objects, so we better make sure these
     // classes are initialized (they already might be)
index 5b91441..48aff58 100644 (file)
@@ -23,6 +23,7 @@ import gov.nasa.jpf.util.MethodInfoRegistry;
 import gov.nasa.jpf.util.RunListener;
 import gov.nasa.jpf.util.RunRegistry;
 
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 
@@ -115,7 +116,7 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
   }
 
   // TODO: Fix for Groovy's model-checking
-  private static int getParameterizedTypeImplObj(String signature, MJIEnv env) {
+  private static int getParameterizedTypeImplObj(String signature, MJIEnv env, int objRef, MethodInfo mi) {
 
     ThreadInfo ti = env.getThreadInfo();
     ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
@@ -133,14 +134,21 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
     ei.setReferenceField("rawType", gci.getClassObjectRef());
 
     // actualTypeArguments
-    String[] parameterizedTypes = Types.getParameterizedTypesFromArgumentTypeNames(signature);
+    String[] parameterizedTypes = Types.getParameterizedTypes(signature);
     int[] types = new int[parameterizedTypes.length];
+    String classGenericSig = mi.getClassInfo().getGenericSignature();
+    String methodGenericSig = mi.getGenericSignature();
     for(int j = 0; j < parameterizedTypes.length; j++) {
-      ClassInfo pci = cli.getResolvedClassInfo(parameterizedTypes[j]);
-      if (!pci.isRegistered()) {
-        pci.registerClass(ti);
+      if (Types.isTypeParameter(parameterizedTypes[j], methodGenericSig) ||
+          Types.isTypeParameter(parameterizedTypes[j], classGenericSig)) {
+        types[j] = getTypeVariableImplObject(env, objRef, mi, parameterizedTypes[j]);
+      } else {
+        ClassInfo pci = cli.getResolvedClassInfo(parameterizedTypes[j]);
+        if (!pci.isRegistered()) {
+          pci.registerClass(ti);
+        }
+        types[j] = pci.getClassObjectRef();
       }
-      types[j] = pci.getClassObjectRef();
     }
     int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", parameterizedTypes.length);
     // Set references for every array element
@@ -164,6 +172,20 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
     return paramTypeRef;
   }
 
+  private static int getTypeVariableImplObject(MJIEnv env, int objRef, MethodInfo mi, String parameterizedType) {
+
+    ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
+    ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
+
+    int typeVarRef = env.newObject(ci);
+    ElementInfo ei = env.getModifiableElementInfo(typeVarRef);
+    // genericDeclaration contains this java.lang.reflect.Method object
+    ei.setReferenceField("genericDeclaration", objRef);
+    ei.setReferenceField("name", env.newString(parameterizedType));
+
+    return typeVarRef;
+  }
+
   static int getGenericParameterTypes( MJIEnv env, int objRef, MethodInfo mi) {
     ThreadInfo ti = env.getThreadInfo();
     String[] argTypeNames = mi.getArgumentGenericTypeNames();
@@ -172,7 +194,7 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
     for (int i = 0; i < argTypeNames.length; i++) {
       // Change this into just the generic class type if it is a generic class
       if (Types.isGenericSignature(argTypeNames[i])) {
-        ar[i] = getParameterizedTypeImplObj(argTypeNames[i], env);
+        ar[i] = getParameterizedTypeImplObj(argTypeNames[i], env, objRef, mi);
       } else {
         ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(argTypeNames[i]);
         if (!ci.isRegistered()) {
@@ -201,7 +223,7 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
 
     int retRef;
     if (Types.isGenericSignature(mi.getGenericReturnTypeName())) {
-      retRef = getParameterizedTypeImplObj(mi.getGenericReturnTypeName(), env);
+      retRef = getParameterizedTypeImplObj(mi.getGenericReturnTypeName(), env, objRef, mi);
     } else {
       ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName());
       if (!ci.isRegistered()) {