From e493412e70a3335deb29a33cfabade4ca45d54de Mon Sep 17 00:00:00 2001 From: rtrimana Date: Mon, 24 Jun 2019 17:18:33 -0700 Subject: [PATCH] Adding tests for Type parameter, wild card, and class types for generic classes. --- examples/Reflection.java | 18 ++++-- src/main/gov/nasa/jpf/vm/Types.java | 33 ++++++++++- .../jpf/vm/JPF_java_lang_reflect_Method.java | 55 +++++++++++++------ 3 files changed, 82 insertions(+), 24 deletions(-) diff --git a/examples/Reflection.java b/examples/Reflection.java index b327158..788ef58 100644 --- a/examples/Reflection.java +++ b/examples/Reflection.java @@ -63,7 +63,10 @@ public class Reflection { for (int i = 0; i < parameters.length; i++) { System.out.println(parameters[i]); } - System.out.println();*/ + System.out.println(); + Type returnType = method.getGenericReturnType(); + System.out.println(returnType);*/ + /*Type superCls = Generic.class.getGenericSuperclass(); //Type superCls = String.class.getGenericSuperclass(); System.out.println(superCls); @@ -73,12 +76,13 @@ public class Reflection { System.out.println(interfaces[i]); }*/ + Method[] methods = Class.class.getMethods(); Method method = null; for(Method mth : methods) { - //if (mth.getName().equals("getConstructor")) { + if (mth.getName().equals("getConstructor")) { //if (mth.getName().equals("isAssignableFrom")) { - if (mth.getName().equals("getTypeParameters")) { + //if (mth.getName().equals("getSuperclass")) { method = mth; } } @@ -88,6 +92,10 @@ public class Reflection { System.out.println(parameters[i]); } System.out.println(); + Type returnType = method.getGenericReturnType(); + System.out.println(returnType); + + /*Class[] parameterTypes = methods[0].getParameterTypes(); for(Class parameterType: parameterTypes){ System.out.println(parameterType.getName()); @@ -107,9 +115,7 @@ public class Reflection { System.out.println(bound); } System.out.println();*/ - Type returnType = method.getGenericReturnType(); - System.out.println(returnType); - + } } diff --git a/src/main/gov/nasa/jpf/vm/Types.java b/src/main/gov/nasa/jpf/vm/Types.java index f9723a6..fcc8ec2 100644 --- a/src/main/gov/nasa/jpf/vm/Types.java +++ b/src/main/gov/nasa/jpf/vm/Types.java @@ -1288,7 +1288,11 @@ public class Types { } public static boolean isWildcardType(String signature) { - return (signature.startsWith("+L") || signature.startsWith("-L") || signature.equals("*")); + return (signature.startsWith("+L") || + signature.startsWith("-L") || + signature.startsWith("+") || + signature.startsWith("-") || + signature.equals("*")); } public static String getWildcardType(String signature) { @@ -1297,5 +1301,32 @@ public class Types { } return signature.replaceAll("\\+L|-L", ""); } + + public static String getTypeParameter(String signature) { + if (signature == null || signature.equals("")) + return signature; + + if (signature.equals("*")) { + return signature; + } + + String cleanSig = signature.replaceAll("\\+|-", ""); + // This kind of signature should be a repetition of its class' type parameter, e.g., TT for Class + if (cleanSig.length()%2 != 0) { + // This is probably a class, e.g., +java.lang.Class + return signature; + } + + // Check that the first and the second halves are the same, e.g., TT for Class + int halfPos = cleanSig.length()/2; + String firstHalf = cleanSig.substring(0, halfPos); + String secondHalf = cleanSig.substring(halfPos, cleanSig.length()); + if (firstHalf.equals(secondHalf)) { + return firstHalf; + } else { + // This is probably a class, e.g., +java.lang.Class + return signature; + } + } // TODO: Fix for Groovy's model-checking } 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 4fcf1d9..5a890df 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 @@ -158,10 +158,10 @@ public class JPF_java_lang_reflect_Method extends NativePeer { String methodGenericSig = mi.getGenericSignature(); for(int j = 0; j < parameterizedTypes.length; j++) { if (Types.isTypeParameter(parameterizedTypes[j], methodGenericSig) || - Types.isTypeParameter(parameterizedTypes[j], classGenericSig)) { + Types.isTypeParameter(parameterizedTypes[j], classGenericSig)) { types[j] = getTypeVariableImplObject(env, objRef, parameterizedTypes[j]); } else if (Types.isWildcardType(parameterizedTypes[j])) { - types[j] = getWildcardTypeImplObject(env, objRef, parameterizedTypes[j]); + types[j] = getWildcardTypeImplObject(env, objRef, parameterizedTypes[j], mi); } else if (Types.isParameterizedType(parameterizedTypes[j])) { // Recursion! types[j] = getParameterizedTypeImplObj(parameterizedTypes[j], env, objRef, mi); @@ -195,29 +195,50 @@ public class JPF_java_lang_reflect_Method extends NativePeer { return paramTypeRef; } - private static int getWildcardTypeImplObject(MJIEnv env, int objRef, String wildcardType) { + private static int getWildcardTypeImplObject(MJIEnv env, int objRef, String wildcardType, MethodInfo mi) { ThreadInfo ti = env.getThreadInfo(); ClassLoaderInfo cli = env.getSystemClassLoaderInfo(); ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.WildcardTypeImpl"); int wildcardRef = env.newObject(ci); ElementInfo ei = env.getModifiableElementInfo(wildcardRef); - String actualType = Types.getWildcardType(wildcardType); - ClassInfo uci = cli.getResolvedClassInfo(actualType); - if (!uci.isRegistered()) { - uci.registerClass(ti); - } + // Type parameter test + // TODO: This test could probably be made cleaner + String classGenericSig = mi.getClassInfo().getGenericSignature(); + String methodGenericSig = mi.getGenericSignature(); + String typeParameter = Types.getTypeParameter(wildcardType); int uRef = MJIEnv.NULL; int lRef = MJIEnv.NULL; - if (wildcardType.startsWith("+L") || wildcardType.equals("*")) { - // Set upperBounds - uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); - env.setReferenceArrayElement(uRef, 0, uci.getClassObjectRef()); - lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0); - } else { // wildcardType.startsWith("-L") - // Set lowerBounds - lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); - env.setReferenceArrayElement(lRef, 0, uci.getClassObjectRef()); + if (Types.isTypeParameter(typeParameter, methodGenericSig) || + Types.isTypeParameter(typeParameter, classGenericSig)) { + int tpRef = getTypeVariableImplObject(env, objRef, typeParameter); + if (wildcardType.startsWith("+")) { + // Set upperBounds + uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); + env.setReferenceArrayElement(uRef, 0, tpRef); + lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0); + } else { // wildcardType.startsWith("-") + // Set lowerBounds + lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); + env.setReferenceArrayElement(lRef, 0, tpRef); + } + } else { + + String actualType = Types.getWildcardType(wildcardType); + ClassInfo uci = cli.getResolvedClassInfo(actualType); + if (!uci.isRegistered()) { + uci.registerClass(ti); + } + if (wildcardType.startsWith("+L") || wildcardType.equals("*")) { + // Set upperBounds + uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); + env.setReferenceArrayElement(uRef, 0, uci.getClassObjectRef()); + lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0); + } else { // wildcardType.startsWith("-L") + // Set lowerBounds + lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1); + env.setReferenceArrayElement(lRef, 0, uci.getClassObjectRef()); + } } ei.setReferenceField("upperBounds", uRef); ei.setReferenceField("lowerBounds", lRef); -- 2.34.1