From 3f0d5734e04323c9734cbb0942f6285cc6afcb68 Mon Sep 17 00:00:00 2001 From: rtrimana Date: Thu, 13 Jun 2019 16:47:25 -0700 Subject: [PATCH] First attempt to add getGenericParameterTypes() and getGenericReturnType(); So far we have not been able to return the generic types with parameters information. --- examples/Reflection.java | 36 +++++++++------- src/main/gov/nasa/jpf/vm/MethodInfo.java | 15 ++++++- src/main/gov/nasa/jpf/vm/Types.java | 28 +++++++++++- .../jpf/vm/JPF_java_lang_reflect_Method.java | 43 +++++++++++++++++-- 4 files changed, 100 insertions(+), 22 deletions(-) diff --git a/examples/Reflection.java b/examples/Reflection.java index ac04e04..4619e4b 100644 --- a/examples/Reflection.java +++ b/examples/Reflection.java @@ -3,58 +3,62 @@ import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.List; +import java.util.Map; import java.util.ArrayList; public class Reflection { - class Generic { + class Generic { } class SampleClass { private String sampleField; - public String getSampleField() { - return sampleField; - } - - /*public List setSampleField(List listString, + public Generic setSampleField(List listString, Map mapString, + Generic test, String sampleField, int one, short two, double three, Object obj) { this.sampleField = sampleField; - return listString; + return test; + } + + /* + public String getSampleField() { + return sampleField; } public void setSampleField(String sampleField) { this.sampleField = sampleField; - }*/ + } public List setSampleField(List listString) { return listString; - } + }*/ } public static void main(String[] args) { Method[] methods = SampleClass.class.getMethods(); - /*Type[] parameters = methods[1].getGenericParameterTypes(); + Type[] parameters = methods[0].getGenericParameterTypes(); + //Type[] parameters = methods[0].getGenericParameterTypes(); for (int i = 0; i < parameters.length; i++) { System.out.println(parameters[i]); } - System.out.println();*/ - Class[] parameterTypes = methods[6].getParameterTypes(); + System.out.println(); + Class[] parameterTypes = methods[0].getParameterTypes(); for(Class parameterType: parameterTypes){ System.out.println(parameterType.getName()); } System.out.println(); - TypeVariable[] typeParameters = Generic.class.getTypeParameters(); + /*TypeVariable[] typeParameters = Generic.class.getTypeParameters(); for(TypeVariable typeVar: typeParameters){ System.out.println(typeVar); } - /*System.out.println(); - Type returnType = methods[1].getGenericReturnType(); - System.out.println(returnType);*/ + System.out.println();*/ + Type returnType = methods[0].getGenericReturnType(); + System.out.println(returnType); } } diff --git a/src/main/gov/nasa/jpf/vm/MethodInfo.java b/src/main/gov/nasa/jpf/vm/MethodInfo.java index a4880c7..a5a83bb 100644 --- a/src/main/gov/nasa/jpf/vm/MethodInfo.java +++ b/src/main/gov/nasa/jpf/vm/MethodInfo.java @@ -502,7 +502,15 @@ public class MethodInfo extends InfoObject implements GenericSignatureHolder { public String[] getArgumentTypeNames () { return Types.getArgumentTypeNames(signature); } - + + // TODO: Fix for Groovy's model-checking + public String[] getArgumentGenericTypeNames () { + // To accommodate methods that do not have generic types + if (genericSignature == "") + return getArgumentTypeNames(); + return Types.getArgumentTypeNames(genericSignature); + } + public int getArgumentsSize () { if (argSize < 0) { argSize = Types.getArgumentsSize(signature); @@ -579,6 +587,11 @@ public class MethodInfo extends InfoObject implements GenericSignatureHolder { public String getReturnTypeName () { return Types.getReturnTypeName(signature); } + + // TODO: Fix for Groovy's model-checking + public String getGenericReturnTypeName () { + return Types.getGenericReturnTypeName(signature); + } public String getSourceFileName () { if (ci != null) { diff --git a/src/main/gov/nasa/jpf/vm/Types.java b/src/main/gov/nasa/jpf/vm/Types.java index ee64f70..c5b2f7f 100644 --- a/src/main/gov/nasa/jpf/vm/Types.java +++ b/src/main/gov/nasa/jpf/vm/Types.java @@ -73,6 +73,9 @@ public class Types { return args; } + // TODO: Fix for Groovy's model-checking + // TODO: We return the generic type name whenever possible (the one between '<' and '>') + // TODO: To do this we fixed the implementation of getTypeLength public static String[] getArgumentTypeNames (String signature) { int len = signature.length(); @@ -95,7 +98,7 @@ public class Types { return typeNames; } - + public static String dequalify (String typeName){ int idx = typeName.lastIndexOf('.'); if (idx > 0) { @@ -585,6 +588,11 @@ public class Types { int i = signature.indexOf(')'); return getTypeName(signature.substring(i+1)); } + + public static String getGenericReturnTypeName (String signature){ + int i = signature.indexOf(')'); + return getTypeName(signature.substring(i+1)); + } public static String getTypeSignature (String type, boolean asDotNotation) { String t = null; @@ -906,9 +914,16 @@ public class Types { int len1 = len-1; if (signature.charAt(len1) == ';') { - return signature.substring(1, len1).replace('/', '.'); + // TODO: Fix for Groovy's model-checking + // TODO: Cleaning up the generic type part inside '<' and '>' + return signature.substring(1, len1).replace('/', '.'). + replaceAll(";L", ", "). + replace("", ">"); } + + throw new JPFException("invalid type string: " + signature); } @@ -1091,6 +1106,15 @@ public class Types { case 'L': int semicolon = signature.indexOf(';', idx); + // TODO: Fix for Groovy's model-checking + // Check if this is a generic! + if (signature.substring(idx,semicolon).indexOf('<') != -1) { + int generic = signature.indexOf('>', semicolon); + if (generic != -1) { + // Advance one character past the ';' + semicolon = generic + 1; + } + } if (semicolon == -1) { throw new JPFException("invalid type signature: " + diff --git a/src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java b/src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java index 964968d..2f485e1 100644 --- a/src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java +++ b/src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java @@ -115,17 +115,54 @@ public class JPF_java_lang_reflect_Method extends NativePeer { } // TODO: Fix for Groovy's model-checking + // TODO: We haven't been able to show the parameterized types + static int getGenericParameterTypes( MJIEnv env, MethodInfo mi) { + ThreadInfo ti = env.getThreadInfo(); + String[] argTypeNames = mi.getArgumentGenericTypeNames(); + int[] ar = new int[argTypeNames.length]; + + for (int i = 0; i < argTypeNames.length; i++) { + // Change this into just the generic class type if it is a generic class + String genericTypeName = argTypeNames[i]; + int startOfGenericParameter = argTypeNames[i].indexOf('<'); + if (startOfGenericParameter != -1) { + genericTypeName = argTypeNames[i].substring(0, startOfGenericParameter); + } + ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(genericTypeName); + if (!ci.isRegistered()) { + ci.registerClass(ti); + } + + ar[i] = ci.getClassObjectRef(); + } + + int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", argTypeNames.length); + for (int i = 0; i < argTypeNames.length; i++) { + env.setReferenceArrayElement(aRef, i, ar[i]); + } + + return aRef; + } + @MJI public int getGenericParameterTypes_____3Ljava_lang_reflect_Type_2 (MJIEnv env, int objRef){ - //return getGenericParameterTypes(env, getMethodInfo(env, objRef)); - return getParameterTypes_____3Ljava_lang_Class_2 (env, objRef); + return getGenericParameterTypes(env, getMethodInfo(env, objRef)); } @MJI public int getGenericReturnType____Ljava_lang_reflect_Type_2 (MJIEnv env, int objRef){ - return getReturnType____Ljava_lang_Class_2(env, objRef); + MethodInfo mi = getMethodInfo(env, objRef); + ThreadInfo ti = env.getThreadInfo(); + + ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName()); + if (!ci.isRegistered()) { + ci.registerClass(ti); + } + + return ci.getClassObjectRef(); } // TODO: Fix for Groovy's model-checking + // TODO: We haven't been able to show the parameterized types int getExceptionTypes(MJIEnv env, MethodInfo mi) { ThreadInfo ti = env.getThreadInfo(); -- 2.34.1