1 /*
   2  * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.internal.reflect;
  27 
  28 import java.io.Externalizable;
  29 import java.io.ObjectInputStream;
  30 import java.io.ObjectOutputStream;
  31 import java.io.ObjectStreamClass;
  32 import java.io.OptionalDataException;
  33 import java.io.Serializable;
  34 import java.lang.invoke.MethodHandle;
  35 import java.lang.invoke.MethodHandles;
  36 import java.lang.reflect.Field;
  37 import java.lang.reflect.Executable;
  38 import java.lang.reflect.InvocationTargetException;
  39 import java.lang.reflect.Method;
  40 import java.lang.reflect.Constructor;
  41 import java.lang.reflect.Modifier;
  42 import java.security.Permission;
  43 import java.security.PrivilegedAction;
  44 import java.util.Objects;
  45 import java.util.Properties;
  46 
  47 import sun.reflect.misc.ReflectUtil;
  48 import sun.security.action.GetPropertyAction;
  49 
  50 /** <P> The master factory for all reflective objects, both those in
  51     java.lang.reflect (Fields, Methods, Constructors) as well as their
  52     delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).
  53     </P>
  54 
  55     <P> The methods in this class are extremely unsafe and can cause
  56     subversion of both the language and the verifier. For this reason,
  57     they are all instance methods, and access to the constructor of
  58     this factory is guarded by a security check, in similar style to
  59     {@link jdk.internal.misc.Unsafe}. </P>
  60 */
  61 
  62 public class ReflectionFactory {
  63 
  64     private static boolean initted = false;
  65     private static final Permission reflectionFactoryAccessPerm
  66         = new RuntimePermission("reflectionFactoryAccess");
  67     private static final ReflectionFactory soleInstance = new ReflectionFactory();
  68     // Provides access to package-private mechanisms in java.lang.reflect
  69     private static volatile LangReflectAccess langReflectAccess;
  70 
  71     /* Method for static class initializer <clinit>, or null */
  72     private static volatile Method hasStaticInitializerMethod;
  73 
  74     //
  75     // "Inflation" mechanism. Loading bytecodes to implement
  76     // Method.invoke() and Constructor.newInstance() currently costs
  77     // 3-4x more than an invocation via native code for the first
  78     // invocation (though subsequent invocations have been benchmarked
  79     // to be over 20x faster). Unfortunately this cost increases
  80     // startup time for certain applications that use reflection
  81     // intensively (but only once per class) to bootstrap themselves.
  82     // To avoid this penalty we reuse the existing JVM entry points
  83     // for the first few invocations of Methods and Constructors and
  84     // then switch to the bytecode-based implementations.
  85     //
  86     // Package-private to be accessible to NativeMethodAccessorImpl
  87     // and NativeConstructorAccessorImpl
  88     private static boolean noInflation        = false;
  89     private static int     inflationThreshold = 15;
  90 
  91     private ReflectionFactory() {
  92     }
  93 
  94     /**
  95      * A convenience class for acquiring the capability to instantiate
  96      * reflective objects.  Use this instead of a raw call to {@link
  97      * #getReflectionFactory} in order to avoid being limited by the
  98      * permissions of your callers.
  99      *
 100      * <p>An instance of this class can be used as the argument of
 101      * <code>AccessController.doPrivileged</code>.
 102      */
 103     public static final class GetReflectionFactoryAction
 104         implements PrivilegedAction<ReflectionFactory> {
 105         public ReflectionFactory run() {
 106             return getReflectionFactory();
 107         }
 108     }
 109 
 110     /**
 111      * Provides the caller with the capability to instantiate reflective
 112      * objects.
 113      *
 114      * <p> First, if there is a security manager, its
 115      * <code>checkPermission</code> method is called with a {@link
 116      * java.lang.RuntimePermission} with target
 117      * <code>"reflectionFactoryAccess"</code>.  This may result in a
 118      * security exception.
 119      *
 120      * <p> The returned <code>ReflectionFactory</code> object should be
 121      * carefully guarded by the caller, since it can be used to read and
 122      * write private data and invoke private methods, as well as to load
 123      * unverified bytecodes.  It must never be passed to untrusted code.
 124      *
 125      * @exception SecurityException if a security manager exists and its
 126      *             <code>checkPermission</code> method doesn't allow
 127      *             access to the RuntimePermission "reflectionFactoryAccess".  */
 128     public static ReflectionFactory getReflectionFactory() {
 129         SecurityManager security = System.getSecurityManager();
 130         if (security != null) {
 131             // TO DO: security.checkReflectionFactoryAccess();
 132             security.checkPermission(reflectionFactoryAccessPerm);
 133         }
 134         return soleInstance;
 135     }
 136 
 137     //--------------------------------------------------------------------------
 138     //
 139     // Routines used by java.lang.reflect
 140     //
 141     //
 142 
 143     /** Called only by java.lang.reflect.Modifier's static initializer */
 144     public void setLangReflectAccess(LangReflectAccess access) {
 145         langReflectAccess = access;
 146     }
 147 
 148     /**
 149      * Note: this routine can cause the declaring class for the field
 150      * be initialized and therefore must not be called until the
 151      * first get/set of this field.
 152      * @param field the field
 153      * @param override true if caller has overridden accessibility
 154      */
 155     public FieldAccessor newFieldAccessor(Field field, boolean override) {
 156         checkInitted();
 157         return UnsafeFieldAccessorFactory.newFieldAccessor(field, override);
 158     }
 159 
 160     public MethodAccessor newMethodAccessor(Method method) {
 161         checkInitted();
 162 
 163         if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
 164             return new MethodAccessorGenerator().
 165                 generateMethod(method.getDeclaringClass(),
 166                                method.getName(),
 167                                method.getParameterTypes(),
 168                                method.getReturnType(),
 169                                method.getExceptionTypes(),
 170                                method.getModifiers());
 171         } else {
 172             NativeMethodAccessorImpl acc =
 173                 new NativeMethodAccessorImpl(method);
 174             DelegatingMethodAccessorImpl res =
 175                 new DelegatingMethodAccessorImpl(acc);
 176             acc.setParent(res);
 177             return res;
 178         }
 179     }
 180 
 181     public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {
 182         checkInitted();
 183 
 184         Class<?> declaringClass = c.getDeclaringClass();
 185         if (Modifier.isAbstract(declaringClass.getModifiers())) {
 186             return new InstantiationExceptionConstructorAccessorImpl(null);
 187         }
 188         if (declaringClass == Class.class) {
 189             return new InstantiationExceptionConstructorAccessorImpl
 190                 ("Can not instantiate java.lang.Class");
 191         }
 192         // Bootstrapping issue: since we use Class.newInstance() in
 193         // the ConstructorAccessor generation process, we have to
 194         // break the cycle here.
 195         if (Reflection.isSubclassOf(declaringClass,
 196                                     ConstructorAccessorImpl.class)) {
 197             return new BootstrapConstructorAccessorImpl(c);
 198         }
 199 
 200         if (noInflation && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
 201             return new MethodAccessorGenerator().
 202                 generateConstructor(c.getDeclaringClass(),
 203                                     c.getParameterTypes(),
 204                                     c.getExceptionTypes(),
 205                                     c.getModifiers());
 206         } else {
 207             NativeConstructorAccessorImpl acc =
 208                 new NativeConstructorAccessorImpl(c);
 209             DelegatingConstructorAccessorImpl res =
 210                 new DelegatingConstructorAccessorImpl(acc);
 211             acc.setParent(res);
 212             return res;
 213         }
 214     }
 215 
 216     //--------------------------------------------------------------------------
 217     //
 218     // Routines used by java.lang
 219     //
 220     //
 221 
 222     /** Creates a new java.lang.reflect.Field. Access checks as per
 223         java.lang.reflect.AccessibleObject are not overridden. */
 224     public Field newField(Class<?> declaringClass,
 225                           String name,
 226                           Class<?> type,
 227                           int modifiers,
 228                           int slot,
 229                           String signature,
 230                           byte[] annotations)
 231     {
 232         return langReflectAccess().newField(declaringClass,
 233                                             name,
 234                                             type,
 235                                             modifiers,
 236                                             slot,
 237                                             signature,
 238                                             annotations);
 239     }
 240 
 241     /** Creates a new java.lang.reflect.Method. Access checks as per
 242         java.lang.reflect.AccessibleObject are not overridden. */
 243     public Method newMethod(Class<?> declaringClass,
 244                             String name,
 245                             Class<?>[] parameterTypes,
 246                             Class<?> returnType,
 247                             Class<?>[] checkedExceptions,
 248                             int modifiers,
 249                             int slot,
 250                             String signature,
 251                             byte[] annotations,
 252                             byte[] parameterAnnotations,
 253                             byte[] annotationDefault)
 254     {
 255         return langReflectAccess().newMethod(declaringClass,
 256                                              name,
 257                                              parameterTypes,
 258                                              returnType,
 259                                              checkedExceptions,
 260                                              modifiers,
 261                                              slot,
 262                                              signature,
 263                                              annotations,
 264                                              parameterAnnotations,
 265                                              annotationDefault);
 266     }
 267 
 268     /** Creates a new java.lang.reflect.Constructor. Access checks as
 269         per java.lang.reflect.AccessibleObject are not overridden. */
 270     public Constructor<?> newConstructor(Class<?> declaringClass,
 271                                          Class<?>[] parameterTypes,
 272                                          Class<?>[] checkedExceptions,
 273                                          int modifiers,
 274                                          int slot,
 275                                          String signature,
 276                                          byte[] annotations,
 277                                          byte[] parameterAnnotations)
 278     {
 279         return langReflectAccess().newConstructor(declaringClass,
 280                                                   parameterTypes,
 281                                                   checkedExceptions,
 282                                                   modifiers,
 283                                                   slot,
 284                                                   signature,
 285                                                   annotations,
 286                                                   parameterAnnotations);
 287     }
 288 
 289     /** Gets the MethodAccessor object for a java.lang.reflect.Method */
 290     public MethodAccessor getMethodAccessor(Method m) {
 291         return langReflectAccess().getMethodAccessor(m);
 292     }
 293 
 294     /** Sets the MethodAccessor object for a java.lang.reflect.Method */
 295     public void setMethodAccessor(Method m, MethodAccessor accessor) {
 296         langReflectAccess().setMethodAccessor(m, accessor);
 297     }
 298 
 299     /** Gets the ConstructorAccessor object for a
 300         java.lang.reflect.Constructor */
 301     public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {
 302         return langReflectAccess().getConstructorAccessor(c);
 303     }
 304 
 305     /** Sets the ConstructorAccessor object for a
 306         java.lang.reflect.Constructor */
 307     public void setConstructorAccessor(Constructor<?> c,
 308                                        ConstructorAccessor accessor)
 309     {
 310         langReflectAccess().setConstructorAccessor(c, accessor);
 311     }
 312 
 313     /** Makes a copy of the passed method. The returned method is a
 314         "child" of the passed one; see the comments in Method.java for
 315         details. */
 316     public Method copyMethod(Method arg) {
 317         return langReflectAccess().copyMethod(arg);
 318     }
 319 
 320     /** Makes a copy of the passed method. The returned method is NOT
 321      * a "child" but a "sibling" of the Method in arg. Should only be
 322      * used on non-root methods. */
 323     public Method leafCopyMethod(Method arg) {
 324         return langReflectAccess().leafCopyMethod(arg);
 325     }
 326 
 327 
 328     /** Makes a copy of the passed field. The returned field is a
 329         "child" of the passed one; see the comments in Field.java for
 330         details. */
 331     public Field copyField(Field arg) {
 332         return langReflectAccess().copyField(arg);
 333     }
 334 
 335     /** Makes a copy of the passed constructor. The returned
 336         constructor is a "child" of the passed one; see the comments
 337         in Constructor.java for details. */
 338     public <T> Constructor<T> copyConstructor(Constructor<T> arg) {
 339         return langReflectAccess().copyConstructor(arg);
 340     }
 341 
 342     /** Gets the byte[] that encodes TypeAnnotations on an executable.
 343      */
 344     public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
 345         return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
 346     }
 347 
 348     public Class<?>[] getExecutableSharedParameterTypes(Executable ex) {
 349         return langReflectAccess().getExecutableSharedParameterTypes(ex);
 350     }
 351 
 352     //--------------------------------------------------------------------------
 353     //
 354     // Routines used by serialization
 355     //
 356     //
 357 
 358     public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
 359         if (!Externalizable.class.isAssignableFrom(cl)) {
 360             return null;
 361         }
 362         try {
 363             Constructor<?> cons = cl.getConstructor();
 364             cons.setAccessible(true);
 365             return cons;
 366         } catch (NoSuchMethodException ex) {
 367             return null;
 368         }
 369     }
 370 
 371     public final Constructor<?> newConstructorForSerialization(Class<?> cl,
 372                                                                Constructor<?> constructorToCall)
 373     {
 374         if (constructorToCall.getDeclaringClass() == cl) {
 375             constructorToCall.setAccessible(true);
 376             return constructorToCall;
 377         }
 378         return generateConstructor(cl, constructorToCall);
 379     }
 380 
 381     public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
 382         Class<?> initCl = cl;
 383         while (Serializable.class.isAssignableFrom(initCl)) {
 384             if ((initCl = initCl.getSuperclass()) == null) {
 385                 return null;
 386             }
 387         }
 388         Constructor<?> constructorToCall;
 389         try {
 390             constructorToCall = initCl.getDeclaredConstructor();
 391             int mods = constructorToCall.getModifiers();
 392             if ((mods & Modifier.PRIVATE) != 0 ||
 393                     ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
 394                             !packageEquals(cl, initCl))) {
 395                 return null;
 396             }
 397         } catch (NoSuchMethodException ex) {
 398             return null;
 399         }
 400         return generateConstructor(cl, constructorToCall);
 401     }
 402 
 403     private final Constructor<?> generateConstructor(Class<?> cl,
 404                                                      Constructor<?> constructorToCall) {
 405 
 406 
 407         ConstructorAccessor acc = new MethodAccessorGenerator().
 408             generateSerializationConstructor(cl,
 409                                              constructorToCall.getParameterTypes(),
 410                                              constructorToCall.getExceptionTypes(),
 411                                              constructorToCall.getModifiers(),
 412                                              constructorToCall.getDeclaringClass());
 413         Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),
 414                                           constructorToCall.getParameterTypes(),
 415                                           constructorToCall.getExceptionTypes(),
 416                                           constructorToCall.getModifiers(),
 417                                           langReflectAccess().
 418                                           getConstructorSlot(constructorToCall),
 419                                           langReflectAccess().
 420                                           getConstructorSignature(constructorToCall),
 421                                           langReflectAccess().
 422                                           getConstructorAnnotations(constructorToCall),
 423                                           langReflectAccess().
 424                                           getConstructorParameterAnnotations(constructorToCall));
 425         setConstructorAccessor(c, acc);
 426         c.setAccessible(true);
 427         return c;
 428     }
 429 
 430     public final MethodHandle readObjectForSerialization(Class<?> cl) {
 431         return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
 432     }
 433 
 434     public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
 435         return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
 436     }
 437 
 438     public final MethodHandle writeObjectForSerialization(Class<?> cl) {
 439         return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
 440     }
 441 
 442     private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
 443                                                                    String methodName,
 444                                                                    Class<?> streamClass) {
 445         if (!Serializable.class.isAssignableFrom(cl)) {
 446             return null;
 447         }
 448 
 449         try {
 450             Method meth = cl.getDeclaredMethod(methodName, streamClass);
 451             int mods = meth.getModifiers();
 452             if (meth.getReturnType() != Void.TYPE ||
 453                     Modifier.isStatic(mods) ||
 454                     !Modifier.isPrivate(mods)) {
 455                 return null;
 456             }
 457             meth.setAccessible(true);
 458             return MethodHandles.lookup().unreflect(meth);
 459         } catch (NoSuchMethodException ex) {
 460             return null;
 461         } catch (IllegalAccessException ex1) {
 462             throw new InternalError("Error", ex1);
 463         }
 464     }
 465 
 466     /**
 467      * Returns a MethodHandle for {@code writeReplace} on the serializable class
 468      * or null if no match found.
 469      * @param cl a serializable class
 470      * @returnss the {@code writeReplace} MethodHandle or {@code null} if not found
 471      */
 472     public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
 473         return getReplaceResolveForSerialization(cl, "writeReplace");
 474     }
 475 
 476     /**
 477      * Returns a MethodHandle for {@code readResolve} on the serializable class
 478      * or null if no match found.
 479      * @param cl a serializable class
 480      * @returns the {@code writeReplace} MethodHandle or {@code null} if not found
 481      */
 482     public final MethodHandle readResolveForSerialization(Class<?> cl) {
 483         return getReplaceResolveForSerialization(cl, "readResolve");
 484     }
 485 
 486     /**
 487      * Lookup readResolve or writeReplace on a class with specified
 488      * signature constraints.
 489      * @param cl a serializable class
 490      * @param methodName the method name to find
 491      * @returns a MethodHandle for the method or {@code null} if not found or
 492      *       has the wrong signature.
 493      */
 494     private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
 495                                                            String methodName) {
 496         if (!Serializable.class.isAssignableFrom(cl)) {
 497             return null;
 498         }
 499 
 500         Class<?> defCl = cl;
 501         while (defCl != null) {
 502             try {
 503                 Method m = defCl.getDeclaredMethod(methodName);
 504                 if (m.getReturnType() != Object.class) {
 505                     return null;
 506                 }
 507                 int mods = m.getModifiers();
 508                 if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
 509                     return null;
 510                 } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
 511                     // fall through
 512                 } else if (Modifier.isPrivate(mods) && (cl != defCl)) {
 513                     return null;
 514                 } else if (!packageEquals(cl, defCl)) {
 515                     return null;
 516                 }
 517                 try {
 518                     // Normal return
 519                     m.setAccessible(true);
 520                     return MethodHandles.lookup().unreflect(m);
 521                 } catch (IllegalAccessException ex0) {
 522                     // setAccessible should prevent IAE
 523                     throw new InternalError("Error", ex0);
 524                 }
 525             } catch (NoSuchMethodException ex) {
 526                 defCl = defCl.getSuperclass();
 527             }
 528         }
 529         return null;
 530     }
 531 
 532     /**
 533      * Returns true if the given class defines a static initializer method,
 534      * false otherwise.
 535      */
 536     public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
 537         Method m = hasStaticInitializerMethod;
 538         if (m == null) {
 539             try {
 540                 m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
 541                         new Class<?>[]{Class.class});
 542                 m.setAccessible(true);
 543                 hasStaticInitializerMethod = m;
 544             } catch (NoSuchMethodException ex) {
 545                 throw new InternalError("No such method hasStaticInitializer on "
 546                         + ObjectStreamClass.class, ex);
 547             }
 548         }
 549         try {
 550             return (Boolean) m.invoke(null, cl);
 551         } catch (InvocationTargetException | IllegalAccessException ex) {
 552             throw new InternalError("Exception invoking hasStaticInitializer", ex);
 553         }
 554     }
 555 
 556     /**
 557      * Return the accessible constructor for OptionalDataException signaling eof.
 558      * @returns the eof constructor for OptionalDataException
 559      */
 560     public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() {
 561         try {
 562             Constructor<OptionalDataException> boolCtor =
 563                     OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
 564             boolCtor.setAccessible(true);
 565             return boolCtor;
 566         } catch (NoSuchMethodException ex) {
 567             throw new InternalError("Constructor not found", ex);
 568         }
 569     }
 570 
 571     //--------------------------------------------------------------------------
 572     //
 573     // Internals only below this point
 574     //
 575 
 576     static int inflationThreshold() {
 577         return inflationThreshold;
 578     }
 579 
 580     /** We have to defer full initialization of this class until after
 581         the static initializer is run since java.lang.reflect.Method's
 582         static initializer (more properly, that for
 583         java.lang.reflect.AccessibleObject) causes this class's to be
 584         run, before the system properties are set up. */
 585     private static void checkInitted() {
 586         if (initted) return;
 587 
 588         // Tests to ensure the system properties table is fully
 589         // initialized. This is needed because reflection code is
 590         // called very early in the initialization process (before
 591         // command-line arguments have been parsed and therefore
 592         // these user-settable properties installed.) We assume that
 593         // if System.out is non-null then the System class has been
 594         // fully initialized and that the bulk of the startup code
 595         // has been run.
 596 
 597         if (System.out == null) {
 598             // java.lang.System not yet fully initialized
 599             return;
 600         }
 601 
 602         Properties props = GetPropertyAction.privilegedGetProperties();
 603         String val = props.getProperty("sun.reflect.noInflation");
 604         if (val != null && val.equals("true")) {
 605             noInflation = true;
 606         }
 607 
 608         val = props.getProperty("sun.reflect.inflationThreshold");
 609         if (val != null) {
 610             try {
 611                 inflationThreshold = Integer.parseInt(val);
 612             } catch (NumberFormatException e) {
 613                 throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e);
 614             }
 615         }
 616 
 617         initted = true;
 618     }
 619 
 620     private static LangReflectAccess langReflectAccess() {
 621         if (langReflectAccess == null) {
 622             // Call a static method to get class java.lang.reflect.Modifier
 623             // initialized. Its static initializer will cause
 624             // setLangReflectAccess() to be called from the context of the
 625             // java.lang.reflect package.
 626             Modifier.isPublic(Modifier.PUBLIC);
 627         }
 628         return langReflectAccess;
 629     }
 630 
 631     /**
 632      * Returns true if classes are defined in the classloader and same package, false
 633      * otherwise.
 634      * @param cl1 a class
 635      * @param cl2 another class
 636      * @returns true if the two classes are in the same classloader and package
 637      */
 638     private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
 639         return cl1.getClassLoader() == cl2.getClassLoader() &&
 640                 Objects.equals(cl1.getPackage(), cl2.getPackage());
 641     }
 642 
 643 }