From 7e89326d6efbc622ba28d368dc9a073c98ba1b73 Mon Sep 17 00:00:00 2001 From: rtrimana Date: Tue, 18 Jun 2019 12:46:45 -0700 Subject: [PATCH] A clean implementation for getTypeParameters' native method version. --- examples/Reflection.java | 5 ++- .../reflectiveObjects/TypeVariableImpl.java | 6 +-- src/main/gov/nasa/jpf/vm/ClassInfo.java | 8 ++++ src/main/gov/nasa/jpf/vm/MethodInfo.java | 2 +- src/main/gov/nasa/jpf/vm/Types.java | 25 +++++++++++++ .../gov/nasa/jpf/vm/JPF_java_lang_Class.java | 37 ++++++++++++------- 6 files changed, 63 insertions(+), 20 deletions(-) diff --git a/examples/Reflection.java b/examples/Reflection.java index 0a021b2..ae0e853 100644 --- a/examples/Reflection.java +++ b/examples/Reflection.java @@ -9,6 +9,9 @@ import java.util.Arrays; public class Reflection { + class GenericShort { + } + class Generic { } @@ -52,7 +55,7 @@ public class Reflection { } System.out.println();*/ - TypeVariable[] typeParameters = Generic.class.getTypeParameters(); + TypeVariable[] typeParameters = GenericShort.class.getTypeParameters(); //TypeVariable[] typeParameters = SampleClass.class.getTypeParameters(); for(TypeVariable typeVar: typeParameters){ System.out.println(typeVar); diff --git a/src/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/src/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java index f845539..50392ca 100644 --- a/src/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java +++ b/src/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java @@ -25,12 +25,9 @@ import sun.reflect.generics.tree.FieldTypeSignature; */ public class TypeVariableImpl extends LazyReflectiveObjectGenerator implements TypeVariable { -//public class TypeVariableImpl { + D genericDeclaration; private String name; - private Type[] bounds; - private FieldTypeSignature[] boundASTs; - //private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; // constructor is private to enforce access through static factory private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs, @@ -38,7 +35,6 @@ public class TypeVariableImpl super(f); genericDeclaration = decl; name = n; - boundASTs = bs; } // Accessors diff --git a/src/main/gov/nasa/jpf/vm/ClassInfo.java b/src/main/gov/nasa/jpf/vm/ClassInfo.java index 83b3f5b..09d59ec 100644 --- a/src/main/gov/nasa/jpf/vm/ClassInfo.java +++ b/src/main/gov/nasa/jpf/vm/ClassInfo.java @@ -2598,6 +2598,14 @@ public class ClassInfo extends InfoObject implements Iterable, Gener public DirectCallStackFrame createRunStartStackFrame (ThreadInfo ti, MethodInfo miRun){ return null; } + + // TODO: Fix for Groovy's model-checking + public String[] getGenericTypeVariableNames () { + // To accommodate methods that do not have generic types + if (genericSignature == null) + return new String[0]; + return Types.getGenericTypeVariableNames(genericSignature); + } } diff --git a/src/main/gov/nasa/jpf/vm/MethodInfo.java b/src/main/gov/nasa/jpf/vm/MethodInfo.java index a5a83bb..1a51c47 100644 --- a/src/main/gov/nasa/jpf/vm/MethodInfo.java +++ b/src/main/gov/nasa/jpf/vm/MethodInfo.java @@ -506,7 +506,7 @@ public class MethodInfo extends InfoObject implements GenericSignatureHolder { // TODO: Fix for Groovy's model-checking public String[] getArgumentGenericTypeNames () { // To accommodate methods that do not have generic types - if (genericSignature == "") + if (genericSignature == null) return getArgumentTypeNames(); return Types.getArgumentTypeNames(genericSignature); } diff --git a/src/main/gov/nasa/jpf/vm/Types.java b/src/main/gov/nasa/jpf/vm/Types.java index c5b2f7f..873b065 100644 --- a/src/main/gov/nasa/jpf/vm/Types.java +++ b/src/main/gov/nasa/jpf/vm/Types.java @@ -1176,5 +1176,30 @@ public class Types { throw new JPFException("invalid method declaration: " + methodDecl); } + + public static String[] getGenericTypeVariableNames(String signature) { + int pos = 0; + int opening = 0; + ArrayList typeVarNames = new ArrayList<>(); + + while (pos < signature.length()) { + if (pos > 0) { + // Start from ';' if this is not the first type variable name + opening = signature.indexOf(';', pos); + // Break if this is the end of the type variable names + if (signature.charAt(opening + 1) == '>') + break; + } + int colon = signature.indexOf(':', pos); + String typeVarName = signature.substring(opening + 1, colon); + typeVarNames.add(typeVarName); + pos = colon + 1; + } + + String[] arrTypeVarNames = new String[typeVarNames.size()]; + typeVarNames.toArray(arrTypeVarNames); + + return arrTypeVarNames; + } } diff --git a/src/peers/gov/nasa/jpf/vm/JPF_java_lang_Class.java b/src/peers/gov/nasa/jpf/vm/JPF_java_lang_Class.java index 9e8fc2b..8ace896 100644 --- a/src/peers/gov/nasa/jpf/vm/JPF_java_lang_Class.java +++ b/src/peers/gov/nasa/jpf/vm/JPF_java_lang_Class.java @@ -110,23 +110,34 @@ public class JPF_java_lang_Class extends NativePeer { } // TODO: Fix for Groovy's model-checking - // TODO: THIS NEEDS TO BE SUBSTITUTED BY THE PROPER METHODS! VERY DIRTY RIGHT NOW! @MJI public int getTypeParameters_____3Ljava_lang_reflect_TypeVariable_2 (MJIEnv env, int robj){ + // Get the ClassInfo for this class + ClassInfo tci = env.getReferredClassInfo(robj); + String[] typeVars = tci.getGenericTypeVariableNames(); + + // Return with null if this is not a generic class + if (typeVars.length == 0) { + int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", 0); + return aRef; + } + // Now create a TypeVariableImpl object for every type variable name; get the ClassInfo for TypeVariableImpl ClassLoaderInfo cli = env.getSystemClassLoaderInfo(); ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl"); - //ClassInfo rci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.Test"); - // TODO: Need to 1) Just create the object of TypeVariableImpl, 2) Declare class type and name only, 3) Return the - // object reference back to the caller - int tvRef = env.newObject(ci); - ElementInfo ei = env.getModifiableElementInfo(tvRef); - - ClassInfo tci = env.getReferredClassInfo( robj); - //ei.setReferenceField("genericDeclaration", env.newObject(tci.getName() + ".class")); - ei.setReferenceField("name", env.newString("TUVW")); - int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", 1); - for (int i = 0; i < 1; i++) { - env.setReferenceArrayElement(aRef, i, tvRef); + int[] var = new int[typeVars.length]; + + for(int i = 0; i < typeVars.length; i++) { + int typeVarRef = env.newObject(ci); + ElementInfo ei = env.getModifiableElementInfo(typeVarRef); + ei.setReferenceField("genericDeclaration", tci.getClassObjectRef()); + ei.setReferenceField("name", env.newString(typeVars[i])); + var[i] = typeVarRef; + } + int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", typeVars.length); + + // Set references for every array element + for (int i = 0; i < typeVars.length; i++) { + env.setReferenceArrayElement(aRef, i, var[i]); } return aRef; -- 2.34.1