3939
4040import org .cprover .CProver ;
4141
42+ /**
43+ * Instances of the class {@code Class} represent classes and
44+ * interfaces in a running Java application. An enum is a kind of
45+ * class and an annotation is a kind of interface. Every array also
46+ * belongs to a class that is reflected as a {@code Class} object
47+ * that is shared by all arrays with the same element type and number
48+ * of dimensions. The primitive Java types ({@code boolean},
49+ * {@code byte}, {@code char}, {@code short},
50+ * {@code int}, {@code long}, {@code float}, and
51+ * {@code double}), and the keyword {@code void} are also
52+ * represented as {@code Class} objects.
53+ *
54+ * <p> {@code Class} has no public constructor. Instead {@code Class}
55+ * objects are constructed automatically by the Java Virtual Machine as classes
56+ * are loaded and by calls to the {@code defineClass} method in the class
57+ * loader.
58+ *
59+ * <p> The following example uses a {@code Class} object to print the
60+ * class name of an object:
61+ *
62+ * <blockquote><pre>
63+ * void printClassName(Object obj) {
64+ * System.out.println("The class of " + obj +
65+ * " is " + obj.getClass().getName());
66+ * }
67+ * </pre></blockquote>
68+ *
69+ * <p> It is also possible to get the {@code Class} object for a named
70+ * type (or for void) using a class literal. See Section 15.8.2 of
71+ * <cite>The Java™ Language Specification</cite>.
72+ * For example:
73+ *
74+ * <blockquote>
75+ * {@code System.out.println("The name of class Foo is: "+Foo.class.getName());}
76+ * </blockquote>
77+ *
78+ * @param <T> the type of the class modeled by this {@code Class}
79+ * object. For example, the type of {@code String.class} is {@code
80+ * Class<String>}. Use {@code Class<?>} if the class being modeled is
81+ * unknown.
82+ *
83+ * @author unascribed
84+ * @see java.lang.ClassLoader#defineClass(byte[], int, int)
85+ * @since JDK1.0
86+ *
87+ * @diffblue.limitedSupport
88+ * Generated tests that create an instance of Class will be incorrect:
89+ * <ul>
90+ * <li>IllegalAccessError error when attempting to set the java.lang.class via reflection</li>
91+ * <li>When JBMC mocks java.lang.Class, it causes IllegalAccessError</li>
92+ * </ul>
93+ */
4294public final class Class <T > {
4395
4496 private Class () {}
@@ -55,6 +107,13 @@ private Class() {}
55107 private boolean cproverIsMemberClass ;
56108 private boolean cproverIsEnum ;
57109
110+ // TODO: these fields are to enforce singleton semantics of
111+ // Class objects as returned by Object.getClass() and Class.forName()
112+ // The size is currently hard-coded which may lead to incorrect results.
113+ // A map could be used here in future.
114+ private static String [] cproverClassNames = new String [8 ];
115+ private static Class <?>[] cproverClassInstances = new Class <?>[8 ];
116+
58117 public String toString () {
59118 return (isInterface () ? "interface " : (isPrimitive () ? "" : "class " ))
60119 + getName ();
@@ -111,9 +170,25 @@ public String toGenericString() {
111170 // forName method. The goal is to correctly model combinations of forName
112171 // and getName, but precisely following the JDK behaviour is more involved.
113172 public static Class <?> forName (String className ) {
114- Class c =new Class ();
115- c .name =className ;
116- return c ;
173+ CProver .notModelled ();
174+ throw new AssertionError ();
175+ /*
176+ String foundName = null;
177+ for (int i = 0; i < cproverClassNames.length; ++i) {
178+ String currentName = cproverClassNames[i];
179+ if (currentName == null) {
180+ Class<?> c = new Class();
181+ c.name = className;
182+ cproverClassNames[i] = className;
183+ cproverClassInstances[i] = c;
184+ return c;
185+ }
186+ if (className.equals(currentName)) {
187+ return cproverClassInstances[i];
188+ }
189+ }
190+ return CProver.nondetWithoutNullForNotModelled();
191+ */
117192 }
118193
119194 public static Class <?> forName (String name , boolean initialize ,
@@ -205,7 +280,7 @@ ClassLoader getClassLoader0() {
205280 // DIFFBLUE MODEL LIBRARY The real java.lang.Class stores a
206281 // `private final ClassLoader classLoader` which is initialised by the
207282 // jvm rather than by the constructor of this object.
208- // TODO test-gen should understand this method natively.
283+ // TODO JBMC should understand this method natively.
209284 return null ;
210285 }
211286
@@ -453,6 +528,7 @@ private static boolean desiredAssertionStatus0(Class<?> clazz) {
453528 protected void cproverNondetInitialize () {
454529 CProver .assume (name != null );
455530 CProver .assume (enumConstantDirectory == null );
531+ CProver .assume (classValueMap == null );
456532 }
457533
458534 // DIFFBLUE MODEL LIBRARY
@@ -607,6 +683,13 @@ public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMe
607683 return new Method (this , name , parameterTypes );
608684 }
609685
686+ // DIFFBLUE MODEL LIBRARY
687+ // This field is never read in our model. We include them because ClassValue
688+ // (in the java library, not our models) references it, so it is needed to
689+ // make ClassValue compile.
690+ // transient ClassValue.ClassValueMap classValueMap;
691+ transient ClassValue .ClassValueMap classValueMap = null ;
692+
610693 /**
611694 * Returns the {@code Class} representing the component type of an
612695 * array. If this class does not represent an array class this method
@@ -615,10 +698,12 @@ public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMe
615698 * @return the {@code Class} representing the component type of this
616699 * class if this class is an array
617700 * @see java.lang.reflect.Array
618- * @since 1.1
701+ * @since JDK1.1
702+ * @diffblue.noSupport
619703 */
704+ // public native Class<?> getComponentType();
620705 public Class <?> getComponentType () {
621706 CProver .notModelled ();
622- return CProver .nondetWithoutNullForNotModelled ();
707+ return CProver .nondetWithNullForNotModelled ();
623708 }
624709}
0 commit comments