jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java
changeset 46174 5611d2529b49
parent 45490 dc68478b53b9
equal deleted inserted replaced
46173:5546b5710844 46174:5611d2529b49
    18  * limitations under the License.
    18  * limitations under the License.
    19  */
    19  */
    20 
    20 
    21 package com.sun.org.apache.bcel.internal.generic;
    21 package com.sun.org.apache.bcel.internal.generic;
    22 
    22 
    23 
    23 import com.sun.org.apache.bcel.internal.Const;
    24 import com.sun.org.apache.bcel.internal.Constants;
       
    25 import com.sun.org.apache.bcel.internal.Repository;
    24 import com.sun.org.apache.bcel.internal.Repository;
    26 import com.sun.org.apache.bcel.internal.classfile.JavaClass;
    25 import com.sun.org.apache.bcel.internal.classfile.JavaClass;
    27 
    26 
    28 /**
    27 /**
    29  * Super class for object and array types.
    28  * Super class for object and array types.
    30  *
    29  *
    31  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
    30  * @version $Id: ReferenceType.java 1749603 2016-06-21 20:50:19Z ggregory $
    32  */
    31  */
    33 public abstract class ReferenceType extends Type {
    32 public abstract class ReferenceType extends Type {
    34   protected ReferenceType(byte t, String s) {
    33 
    35     super(t, s);
    34     protected ReferenceType(final byte t, final String s) {
    36   }
    35         super(t, s);
    37 
    36     }
    38   /** Class is non-abstract but not instantiable from the outside
    37 
    39    */
    38 
    40   ReferenceType() {
    39     /** Class is non-abstract but not instantiable from the outside
    41     super(Constants.T_OBJECT, "<null object>");
    40      */
    42   }
    41     ReferenceType() {
    43 
    42         super(Const.T_OBJECT, "<null object>");
    44   /**
    43     }
    45    * Return true iff this type is castable to another type t as defined in
    44 
    46    * the JVM specification.  The case where this is Type.NULL is not
    45 
    47    * defined (see the CHECKCAST definition in the JVM specification).
    46     /**
    48    * However, because e.g. CHECKCAST doesn't throw a
    47      * Return true iff this type is castable to another type t as defined in
    49    * ClassCastException when casting a null reference to any Object,
    48      * the JVM specification.  The case where this is Type.NULL is not
    50    * true is returned in this case.
    49      * defined (see the CHECKCAST definition in the JVM specification).
    51    */
    50      * However, because e.g. CHECKCAST doesn't throw a
    52   public boolean isCastableTo(Type t) {
    51      * ClassCastException when casting a null reference to any Object,
    53     if (this.equals(Type.NULL))
    52      * true is returned in this case.
    54       return true;              // If this is ever changed in isAssignmentCompatible()
    53      *
    55 
    54      * @throws ClassNotFoundException if any classes or interfaces required
    56     return isAssignmentCompatibleWith(t);
    55      *  to determine assignment compatibility can't be found
    57     /* Yes, it's true: It's the same definition.
    56      */
    58      * See vmspec2 AASTORE / CHECKCAST definitions.
    57     public boolean isCastableTo( final Type t ) throws ClassNotFoundException {
    59      */
    58         if (this.equals(Type.NULL)) {
    60   }
    59             return t instanceof ReferenceType; // If this is ever changed in isAssignmentCompatible()
    61 
    60         }
    62   /**
    61         return isAssignmentCompatibleWith(t);
    63    * Return true iff this is assignment compatible with another type t
    62         /* Yes, it's true: It's the same definition.
    64    * as defined in the JVM specification; see the AASTORE definition
    63          * See vmspec2 AASTORE / CHECKCAST definitions.
    65    * there.
       
    66    */
       
    67   public boolean isAssignmentCompatibleWith(Type t) {
       
    68     if (!(t instanceof ReferenceType))
       
    69       return false;
       
    70 
       
    71     ReferenceType T = (ReferenceType) t;
       
    72 
       
    73     if (this.equals(Type.NULL))
       
    74       return true; // This is not explicitely stated, but clear. Isn't it?
       
    75 
       
    76     /* If this is a class type then
       
    77      */
       
    78     if ((this instanceof ObjectType) && (((ObjectType) this).referencesClass())) {
       
    79       /* If T is a class type, then this must be the same class as T,
       
    80          or this must be a subclass of T;
       
    81       */
       
    82       if ((T instanceof ObjectType) && (((ObjectType) T).referencesClass())) {
       
    83         if (this.equals(T))
       
    84           return true;
       
    85 
       
    86         if (Repository.instanceOf(((ObjectType) this).getClassName(),
       
    87                                   ((ObjectType) T).getClassName()))
       
    88           return true;
       
    89       }
       
    90 
       
    91       /* If T is an interface type, this must implement interface T.
       
    92        */
       
    93       if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterface())) {
       
    94         if (Repository.implementationOf(((ObjectType) this).getClassName(),
       
    95                                         ((ObjectType) T).getClassName()))
       
    96           return true;
       
    97       }
       
    98     }
       
    99 
       
   100     /* If this is an interface type, then:
       
   101      */
       
   102     if ((this instanceof ObjectType) && (((ObjectType) this).referencesInterface())) {
       
   103       /* If T is a class type, then T must be Object (2.4.7).
       
   104        */
       
   105       if ((T instanceof ObjectType) && (((ObjectType) T).referencesClass())) {
       
   106         if (T.equals(Type.OBJECT)) return true;
       
   107       }
       
   108 
       
   109       /* If T is an interface type, then T must be the same interface
       
   110        * as this or a superinterface of this (2.13.2).
       
   111        */
       
   112       if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterface())) {
       
   113         if (this.equals(T)) return true;
       
   114         if (Repository.implementationOf(((ObjectType) this).getClassName(),
       
   115                                         ((ObjectType) T).getClassName()))
       
   116           return true;
       
   117       }
       
   118     }
       
   119 
       
   120     /* If this is an array type, namely, the type SC[], that is, an
       
   121      * array of components of type SC, then:
       
   122      */
       
   123     if (this instanceof ArrayType) {
       
   124       /* If T is a class type, then T must be Object (2.4.7).
       
   125        */
       
   126       if ((T instanceof ObjectType) && (((ObjectType) T).referencesClass())) {
       
   127         if (T.equals(Type.OBJECT)) return true;
       
   128       }
       
   129 
       
   130       /* If T is an array type TC[], that is, an array of components
       
   131        * of type TC, then one of the following must be true:
       
   132        */
       
   133       if (T instanceof ArrayType) {
       
   134         /* TC and SC are the same primitive type (2.4.1).
       
   135          */
    64          */
   136         Type sc = ((ArrayType) this).getElementType();
    65     }
   137         Type tc = ((ArrayType) this).getElementType();
    66 
   138 
    67 
   139         if (sc instanceof BasicType && tc instanceof BasicType && sc.equals(tc))
    68     /**
   140           return true;
    69      * Return true iff this is assignment compatible with another type t
   141 
    70      * as defined in the JVM specification; see the AASTORE definition
   142         /* TC and SC are reference types (2.4.6), and type SC is
    71      * there.
   143          * assignable to TC by these runtime rules.
    72      * @throws ClassNotFoundException if any classes or interfaces required
       
    73      *  to determine assignment compatibility can't be found
       
    74      */
       
    75     public boolean isAssignmentCompatibleWith( final Type t ) throws ClassNotFoundException {
       
    76         if (!(t instanceof ReferenceType)) {
       
    77             return false;
       
    78         }
       
    79         final ReferenceType T = (ReferenceType) t;
       
    80         if (this.equals(Type.NULL)) {
       
    81             return true; // This is not explicitely stated, but clear. Isn't it?
       
    82         }
       
    83         /* If this is a class type then
   144          */
    84          */
   145         if (tc instanceof ReferenceType && sc instanceof ReferenceType &&
    85         if ((this instanceof ObjectType) && (((ObjectType) this).referencesClassExact())) {
   146             ((ReferenceType) sc).isAssignmentCompatibleWith((ReferenceType) tc))
    86             /* If T is a class type, then this must be the same class as T,
   147           return true;
    87              or this must be a subclass of T;
   148       }
    88              */
   149 
    89             if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) {
   150       /* If T is an interface type, T must be one of the interfaces implemented by arrays (2.15). */
    90                 if (this.equals(T)) {
   151       // TODO: Check if this is still valid or find a way to dynamically find out which
    91                     return true;
   152       // interfaces arrays implement. However, as of the JVM specification edition 2, there
    92                 }
   153       // are at least two different pages where assignment compatibility is defined and
    93                 if (Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T)
   154       // on one of them "interfaces implemented by arrays" is exchanged with "'Cloneable' or
    94                         .getClassName())) {
   155       // 'java.io.Serializable'"
    95                     return true;
   156       if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterface())) {
    96                 }
   157         for (int ii = 0; ii < Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS.length; ii++) {
    97             }
   158           if (T.equals(new ObjectType(Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS[ii]))) return true;
    98             /* If T is an interface type, this must implement interface T.
   159         }
    99              */
   160       }
   100             if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) {
   161     }
   101                 if (Repository.implementationOf(((ObjectType) this).getClassName(),
   162     return false; // default.
   102                         ((ObjectType) T).getClassName())) {
   163   }
   103                     return true;
   164 
   104                 }
   165   /**
   105             }
   166    * This commutative operation returns the first common superclass (narrowest ReferenceType
   106         }
   167    * referencing a class, not an interface).
   107         /* If this is an interface type, then:
   168    * If one of the types is a superclass of the other, the former is returned.
   108          */
   169    * If "this" is Type.NULL, then t is returned.
   109         if ((this instanceof ObjectType) && (((ObjectType) this).referencesInterfaceExact())) {
   170    * If t is Type.NULL, then "this" is returned.
   110             /* If T is a class type, then T must be Object (2.4.7).
   171    * If "this" equals t ['this.equals(t)'] "this" is returned.
   111              */
   172    * If "this" or t is an ArrayType, then Type.OBJECT is returned;
   112             if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) {
   173    * unless their dimensions match. Then an ArrayType of the same
   113                 if (T.equals(Type.OBJECT)) {
   174    * number of dimensions is returned, with its basic type being the
   114                     return true;
   175    * first common super class of the basic types of "this" and t.
   115                 }
   176    * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
   116             }
   177    * If not all of the two classes' superclasses cannot be found, "null" is returned.
   117             /* If T is an interface type, then T must be the same interface
   178    * See the JVM specification edition 2, "4.9.2 The Bytecode Verifier".
   118              * as this or a superinterface of this (2.13.2).
   179    */
   119              */
   180   public ReferenceType getFirstCommonSuperclass(ReferenceType t) {
   120             if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) {
   181     if (this.equals(Type.NULL)) return t;
   121                 if (this.equals(T)) {
   182     if (t.equals(Type.NULL)) return this;
   122                     return true;
   183     if (this.equals(t)) return this;
   123                 }
   184     /*
   124                 if (Repository.implementationOf(((ObjectType) this).getClassName(),
   185      * TODO: Above sounds a little arbitrary. On the other hand, there is
   125                         ((ObjectType) T).getClassName())) {
   186      * no object referenced by Type.NULL so we can also say all the objects
   126                     return true;
   187      * referenced by Type.NULL were derived from java.lang.Object.
   127                 }
   188      * However, the Java Language's "instanceof" operator proves us wrong:
   128             }
   189      * "null" is not referring to an instance of java.lang.Object :)
   129         }
   190      */
   130         /* If this is an array type, namely, the type SC[], that is, an
   191 
   131          * array of components of type SC, then:
   192     /* This code is from a bug report by Konstantin Shagin <konst@cs.technion.ac.il> */
   132          */
   193 
   133         if (this instanceof ArrayType) {
   194     if ((this instanceof ArrayType) && (t instanceof ArrayType)) {
   134             /* If T is a class type, then T must be Object (2.4.7).
   195       ArrayType arrType1 = (ArrayType) this;
   135              */
   196       ArrayType arrType2 = (ArrayType) t;
   136             if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) {
   197       if (
   137                 if (T.equals(Type.OBJECT)) {
   198           (arrType1.getDimensions() == arrType2.getDimensions()) &&
   138                     return true;
   199           arrType1.getBasicType() instanceof ObjectType &&
   139                 }
   200           arrType2.getBasicType() instanceof ObjectType) {
   140             }
   201         return new ArrayType(
   141             /* If T is an array type TC[], that is, an array of components
   202                              ((ObjectType) arrType1.getBasicType()).getFirstCommonSuperclass((ObjectType) arrType2.getBasicType()),
   142              * of type TC, then one of the following must be true:
   203                              arrType1.getDimensions()
   143              */
   204                              );
   144             if (T instanceof ArrayType) {
   205 
   145                 /* TC and SC are the same primitive type (2.4.1).
   206       }
   146                  */
   207     }
   147                 final Type sc = ((ArrayType) this).getElementType();
   208 
   148                 final Type tc = ((ArrayType) T).getElementType();
   209     if ((this instanceof ArrayType) || (t instanceof ArrayType))
   149                 if (sc instanceof BasicType && tc instanceof BasicType && sc.equals(tc)) {
   210       return Type.OBJECT;
   150                     return true;
   211     // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
   151                 }
   212 
   152                 /* TC and SC are reference types (2.4.6), and type SC is
   213     if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface()) ||
   153                  * assignable to TC by these runtime rules.
   214         ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface()))
   154                  */
   215       return Type.OBJECT;
   155                 if (tc instanceof ReferenceType && sc instanceof ReferenceType
   216     // TODO: The above line is correct comparing to the vmspec2. But one could
   156                         && ((ReferenceType) sc).isAssignmentCompatibleWith(tc)) {
   217     // make class file verification a bit stronger here by using the notion of
   157                     return true;
   218     // superinterfaces or even castability or assignment compatibility.
   158                 }
   219 
   159             }
   220 
   160             /* If T is an interface type, T must be one of the interfaces implemented by arrays (2.15). */
   221     // this and t are ObjectTypes, see above.
   161             // TODO: Check if this is still valid or find a way to dynamically find out which
   222     ObjectType thiz = (ObjectType) this;
   162             // interfaces arrays implement. However, as of the JVM specification edition 2, there
   223     ObjectType other = (ObjectType) t;
   163             // are at least two different pages where assignment compatibility is defined and
   224     JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
   164             // on one of them "interfaces implemented by arrays" is exchanged with "'Cloneable' or
   225     JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
   165             // 'java.io.Serializable'"
   226 
   166             if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) {
   227     if ((thiz_sups == null) || (other_sups == null)) {
   167                 for (final String element : Const.getInterfacesImplementedByArrays()) {
   228       return null;
   168                     if (T.equals(ObjectType.getInstance(element))) {
   229     }
   169                         return true;
   230 
   170                     }
   231     // Waaahh...
   171                 }
   232     JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
   172             }
   233     JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
   173         }
   234     System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
   174         return false; // default.
   235     System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
   175     }
   236     this_sups[0] = Repository.lookupClass(thiz.getClassName());
   176 
   237     t_sups[0] = Repository.lookupClass(other.getClassName());
   177 
   238 
   178     /**
   239     for (int i = 0; i < t_sups.length; i++) {
   179      * This commutative operation returns the first common superclass (narrowest ReferenceType
   240       for (int j = 0; j < this_sups.length; j++) {
   180      * referencing a class, not an interface).
   241         if (this_sups[j].equals(t_sups[i])) return new ObjectType(this_sups[j].getClassName());
   181      * If one of the types is a superclass of the other, the former is returned.
   242       }
   182      * If "this" is Type.NULL, then t is returned.
   243     }
   183      * If t is Type.NULL, then "this" is returned.
   244 
   184      * If "this" equals t ['this.equals(t)'] "this" is returned.
   245     // Huh? Did you ask for Type.OBJECT's superclass??
   185      * If "this" or t is an ArrayType, then Type.OBJECT is returned;
   246     return null;
   186      * unless their dimensions match. Then an ArrayType of the same
   247   }
   187      * number of dimensions is returned, with its basic type being the
   248 
   188      * first common super class of the basic types of "this" and t.
   249   /**
   189      * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
   250    * This commutative operation returns the first common superclass (narrowest ReferenceType
   190      * If not all of the two classes' superclasses cannot be found, "null" is returned.
   251    * referencing a class, not an interface).
   191      * See the JVM specification edition 2, "4.9.2 The Bytecode Verifier".
   252    * If one of the types is a superclass of the other, the former is returned.
   192      *
   253    * If "this" is Type.NULL, then t is returned.
   193      * @throws ClassNotFoundException on failure to find superclasses of this
   254    * If t is Type.NULL, then "this" is returned.
   194      *  type, or the type passed as a parameter
   255    * If "this" equals t ['this.equals(t)'] "this" is returned.
   195      */
   256    * If "this" or t is an ArrayType, then Type.OBJECT is returned.
   196     public ReferenceType getFirstCommonSuperclass( final ReferenceType t ) throws ClassNotFoundException {
   257    * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
   197         if (this.equals(Type.NULL)) {
   258    * If not all of the two classes' superclasses cannot be found, "null" is returned.
   198             return t;
   259    * See the JVM specification edition 2, "4.9.2 The Bytecode Verifier".
   199         }
   260    *
   200         if (t.equals(Type.NULL)) {
   261    * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has
   201             return this;
   262    *             slightly changed semantics.
   202         }
   263    */
   203         if (this.equals(t)) {
   264   @Deprecated
   204             return this;
   265   public ReferenceType firstCommonSuperclass(ReferenceType t) {
   205             /*
   266     if (this.equals(Type.NULL)) return t;
   206              * TODO: Above sounds a little arbitrary. On the other hand, there is
   267     if (t.equals(Type.NULL)) return this;
   207              * no object referenced by Type.NULL so we can also say all the objects
   268     if (this.equals(t)) return this;
   208              * referenced by Type.NULL were derived from java.lang.Object.
   269     /*
   209              * However, the Java Language's "instanceof" operator proves us wrong:
   270      * TODO: Above sounds a little arbitrary. On the other hand, there is
   210              * "null" is not referring to an instance of java.lang.Object :)
   271      * no object referenced by Type.NULL so we can also say all the objects
   211              */
   272      * referenced by Type.NULL were derived from java.lang.Object.
   212         }
   273      * However, the Java Language's "instanceof" operator proves us wrong:
   213         /* This code is from a bug report by Konstantin Shagin <konst@cs.technion.ac.il> */
   274      * "null" is not referring to an instance of java.lang.Object :)
   214         if ((this instanceof ArrayType) && (t instanceof ArrayType)) {
   275      */
   215             final ArrayType arrType1 = (ArrayType) this;
   276 
   216             final ArrayType arrType2 = (ArrayType) t;
   277     if ((this instanceof ArrayType) || (t instanceof ArrayType))
   217             if ((arrType1.getDimensions() == arrType2.getDimensions())
   278       return Type.OBJECT;
   218                     && arrType1.getBasicType() instanceof ObjectType
   279     // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
   219                     && arrType2.getBasicType() instanceof ObjectType) {
   280 
   220                 return new ArrayType(((ObjectType) arrType1.getBasicType())
   281     if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface()) ||
   221                         .getFirstCommonSuperclass((ObjectType) arrType2.getBasicType()), arrType1
   282         ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface()))
   222                         .getDimensions());
   283       return Type.OBJECT;
   223             }
   284     // TODO: The above line is correct comparing to the vmspec2. But one could
   224         }
   285     // make class file verification a bit stronger here by using the notion of
   225         if ((this instanceof ArrayType) || (t instanceof ArrayType)) {
   286     // superinterfaces or even castability or assignment compatibility.
   226             return Type.OBJECT;
   287 
   227             // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
   288 
   228         }
   289     // this and t are ObjectTypes, see above.
   229         if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterfaceExact())
   290     ObjectType thiz = (ObjectType) this;
   230                 || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterfaceExact())) {
   291     ObjectType other = (ObjectType) t;
   231             return Type.OBJECT;
   292     JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
   232             // TODO: The above line is correct comparing to the vmspec2. But one could
   293     JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
   233             // make class file verification a bit stronger here by using the notion of
   294 
   234             // superinterfaces or even castability or assignment compatibility.
   295     if ((thiz_sups == null) || (other_sups == null)) {
   235         }
   296       return null;
   236         // this and t are ObjectTypes, see above.
   297     }
   237         final ObjectType thiz = (ObjectType) this;
   298 
   238         final ObjectType other = (ObjectType) t;
   299     // Waaahh...
   239         final JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
   300     JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
   240         final JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
   301     JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
   241         if ((thiz_sups == null) || (other_sups == null)) {
   302     System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
   242             return null;
   303     System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
   243         }
   304     this_sups[0] = Repository.lookupClass(thiz.getClassName());
   244         // Waaahh...
   305     t_sups[0] = Repository.lookupClass(other.getClassName());
   245         final JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
   306 
   246         final JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
   307     for (int i = 0; i < t_sups.length; i++) {
   247         System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
   308       for (int j = 0; j < this_sups.length; j++) {
   248         System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
   309         if (this_sups[j].equals(t_sups[i])) return new ObjectType(this_sups[j].getClassName());
   249         this_sups[0] = Repository.lookupClass(thiz.getClassName());
   310       }
   250         t_sups[0] = Repository.lookupClass(other.getClassName());
   311     }
   251         for (final JavaClass t_sup : t_sups) {
   312 
   252             for (final JavaClass this_sup : this_sups) {
   313     // Huh? Did you ask for Type.OBJECT's superclass??
   253                 if (this_sup.equals(t_sup)) {
   314     return null;
   254                     return ObjectType.getInstance(this_sup.getClassName());
   315   }
   255                 }
       
   256             }
       
   257         }
       
   258         // Huh? Did you ask for Type.OBJECT's superclass??
       
   259         return null;
       
   260     }
       
   261 
       
   262     /**
       
   263      * This commutative operation returns the first common superclass (narrowest ReferenceType
       
   264      * referencing a class, not an interface).
       
   265      * If one of the types is a superclass of the other, the former is returned.
       
   266      * If "this" is Type.NULL, then t is returned.
       
   267      * If t is Type.NULL, then "this" is returned.
       
   268      * If "this" equals t ['this.equals(t)'] "this" is returned.
       
   269      * If "this" or t is an ArrayType, then Type.OBJECT is returned.
       
   270      * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
       
   271      * If not all of the two classes' superclasses cannot be found, "null" is returned.
       
   272      * See the JVM specification edition 2, "4.9.2 The Bytecode Verifier".
       
   273      *
       
   274      * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has
       
   275      *             slightly changed semantics.
       
   276      * @throws ClassNotFoundException on failure to find superclasses of this
       
   277      *  type, or the type passed as a parameter
       
   278      */
       
   279     @Deprecated
       
   280     public ReferenceType firstCommonSuperclass( final ReferenceType t ) throws ClassNotFoundException {
       
   281         if (this.equals(Type.NULL)) {
       
   282             return t;
       
   283         }
       
   284         if (t.equals(Type.NULL)) {
       
   285             return this;
       
   286         }
       
   287         if (this.equals(t)) {
       
   288             return this;
       
   289             /*
       
   290              * TODO: Above sounds a little arbitrary. On the other hand, there is
       
   291              * no object referenced by Type.NULL so we can also say all the objects
       
   292              * referenced by Type.NULL were derived from java.lang.Object.
       
   293              * However, the Java Language's "instanceof" operator proves us wrong:
       
   294              * "null" is not referring to an instance of java.lang.Object :)
       
   295              */
       
   296         }
       
   297         if ((this instanceof ArrayType) || (t instanceof ArrayType)) {
       
   298             return Type.OBJECT;
       
   299             // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
       
   300         }
       
   301         if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface())
       
   302                 || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface())) {
       
   303             return Type.OBJECT;
       
   304             // TODO: The above line is correct comparing to the vmspec2. But one could
       
   305             // make class file verification a bit stronger here by using the notion of
       
   306             // superinterfaces or even castability or assignment compatibility.
       
   307         }
       
   308         // this and t are ObjectTypes, see above.
       
   309         final ObjectType thiz = (ObjectType) this;
       
   310         final ObjectType other = (ObjectType) t;
       
   311         final JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
       
   312         final JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
       
   313         if ((thiz_sups == null) || (other_sups == null)) {
       
   314             return null;
       
   315         }
       
   316         // Waaahh...
       
   317         final JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
       
   318         final JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
       
   319         System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
       
   320         System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
       
   321         this_sups[0] = Repository.lookupClass(thiz.getClassName());
       
   322         t_sups[0] = Repository.lookupClass(other.getClassName());
       
   323         for (final JavaClass t_sup : t_sups) {
       
   324             for (final JavaClass this_sup : this_sups) {
       
   325                 if (this_sup.equals(t_sup)) {
       
   326                     return ObjectType.getInstance(this_sup.getClassName());
       
   327                 }
       
   328             }
       
   329         }
       
   330         // Huh? Did you ask for Type.OBJECT's superclass??
       
   331         return null;
       
   332     }
   316 }
   333 }