Source for java.lang.reflect.Proxy

   1: /* Proxy.java -- build a proxy class that implements reflected interfaces
   2:    Copyright (C) 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.lang.reflect;
  40: 
  41: import gnu.classpath.Configuration;
  42: import gnu.java.lang.reflect.TypeSignature;
  43: 
  44: import java.io.Serializable;
  45: import java.security.ProtectionDomain;
  46: import java.util.HashMap;
  47: import java.util.HashSet;
  48: import java.util.Iterator;
  49: import java.util.Map;
  50: import java.util.Set;
  51: 
  52: /**
  53:  * This class allows you to dynamically create an instance of any (or
  54:  * even multiple) interfaces by reflection, and decide at runtime
  55:  * how that instance will behave by giving it an appropriate
  56:  * {@link InvocationHandler}.  Proxy classes serialize specially, so
  57:  * that the proxy object can be reused between VMs, without requiring
  58:  * a persistent copy of the generated class code.
  59:  *
  60:  * <h3>Creation</h3>
  61:  * To create a proxy for some interface Foo:
  62:  *
  63:  * <pre>
  64:  *   InvocationHandler handler = new MyInvocationHandler(...);
  65:  *   Class proxyClass = Proxy.getProxyClass(
  66:  *       Foo.class.getClassLoader(), new Class[] { Foo.class });
  67:  *   Foo f = (Foo) proxyClass
  68:  *       .getConstructor(new Class[] { InvocationHandler.class })
  69:  *       .newInstance(new Object[] { handler });
  70:  * </pre>
  71:  * or more simply:
  72:  * <pre>
  73:  *   Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
  74:  *                                        new Class[] { Foo.class },
  75:  *                                        handler);
  76:  * </pre>
  77:  *
  78:  * <h3>Dynamic Proxy Classes</h3>
  79:  * A dynamic proxy class is created at runtime, and has the following
  80:  * properties:
  81:  * <ul>
  82:  *  <li>The class is <code>public</code> and <code>final</code>,
  83:  *      and is neither <code>abstract</code> nor an inner class.</li>
  84:  *  <li>The class has no canonical name (there is no formula you can use
  85:  *      to determine or generate its name), but begins with the
  86:  *      sequence "$Proxy".  Abuse this knowledge at your own peril.
  87:  *      (For now, '$' in user identifiers is legal, but it may not
  88:  *      be that way forever. You weren't using '$' in your
  89:  *      identifiers, were you?)</li>
  90:  *  <li>The class extends Proxy, and explicitly implements all the
  91:  *      interfaces specified at creation, in order (this is important
  92:  *      for determining how method invocation is resolved).  Note that
  93:  *      a proxy class implements {@link Serializable}, at least
  94:  *      implicitly, since Proxy does, but true serial behavior
  95:  *      depends on using a serializable invocation handler as well.</li>
  96:  *  <li>If at least one interface is non-public, the proxy class
  97:  *      will be in the same package.  Otherwise, the package is
  98:  *      unspecified.  This will work even if the package is sealed
  99:  *      from user-generated classes, because Proxy classes are
 100:  *      generated by a trusted source.  Meanwhile, the proxy class
 101:  *      belongs to the classloader you designated.</li>
 102:  *  <li>Reflection works as expected: {@link Class#getInterfaces()} and
 103:  *      {@link Class#getMethods()} work as they do on normal classes.</li>
 104:  *  <li>The method {@link #isProxyClass()} will distinguish between
 105:  *      true proxy classes and user extensions of this class.  It only
 106:  *      returns true for classes created by {@link #getProxyClass}.</li>
 107:  *  <li>The {@link ProtectionDomain} of a proxy class is the same as for
 108:  *      bootstrap classes, such as Object or Proxy, since it is created by
 109:  *      a trusted source.  This protection domain will typically be granted
 110:  *      {@link java.security.AllPermission}. But this is not a security
 111:  *      risk, since there are adequate permissions on reflection, which is
 112:  *      the only way to create an instance of the proxy class.</li>
 113:  *  <li>The proxy class contains a single constructor, which takes as
 114:  *      its only argument an {@link InvocationHandler}.  The method
 115:  *      {@link #newInstance} is shorthand to do the necessary
 116:  *      reflection.</li>
 117:  * </ul>
 118:  *
 119:  * <h3>Proxy Instances</h3>
 120:  * A proxy instance is an instance of a proxy class.  It has the
 121:  * following properties, many of which follow from the properties of a
 122:  * proxy class listed above:
 123:  * <ul>
 124:  *  <li>For a proxy class with Foo listed as one of its interfaces, the
 125:  *      expression <code>proxy instanceof Foo</code> will return true,
 126:  *      and the expression <code>(Foo) proxy</code> will succeed without
 127:  *      a {@link ClassCastException}.</li>
 128:  *  <li>Each proxy instance has an invocation handler, which can be
 129:  *      accessed by {@link #getInvocationHandler(Object)}.  Any call
 130:  *      to an interface method, including {@link Object#hashcode()},
 131:  *      {@link Object#equals(Object)}, or {@link Object#toString()},
 132:  *      but excluding the public final methods of Object, will be
 133:  *      encoded and passed to the {@link InvocationHandler#invoke}
 134:  *      method of this handler.</li>
 135:  * </ul>
 136:  *
 137:  * <h3>Inheritance Issues</h3>
 138:  * A proxy class may inherit a method from more than one interface.
 139:  * The order in which interfaces are listed matters, because it determines
 140:  * which reflected {@link Method} object will be passed to the invocation
 141:  * handler.  This means that the dynamically generated class cannot
 142:  * determine through which interface a method is being invoked.<p>
 143:  *
 144:  * In short, if a method is declared in Object (namely, hashCode,
 145:  * equals, or toString), then Object will be used; otherwise, the
 146:  * leftmost interface that inherits or declares a method will be used,
 147:  * even if it has a more permissive throws clause than what the proxy
 148:  * class is allowed. Thus, in the invocation handler, it is not always
 149:  * safe to assume that every class listed in the throws clause of the
 150:  * passed Method object can safely be thrown; fortunately, the Proxy
 151:  * instance is robust enough to wrap all illegal checked exceptions in
 152:  * {@link UndeclaredThrowableException}.
 153:  *
 154:  * @see InvocationHandler
 155:  * @see UndeclaredThrowableException
 156:  * @see Class
 157:  * @author Eric Blake (ebb9@email.byu.edu)
 158:  * @since 1.3
 159:  * @status updated to 1.4, except for the use of ProtectionDomain
 160:  */
 161: public class Proxy implements Serializable
 162: {
 163:   /**
 164:    * Compatible with JDK 1.3+.
 165:    */
 166:   private static final long serialVersionUID = -2222568056686623797L;
 167: 
 168:   /**
 169:    * Map of ProxyType to proxy class.
 170:    *
 171:    * @XXX This prevents proxy classes from being garbage collected.
 172:    * java.util.WeakHashSet is not appropriate, because that collects the
 173:    * keys, but we are interested in collecting the elements.
 174:    */
 175:   private static final Map proxyClasses = new HashMap();
 176: 
 177:   /**
 178:    * The invocation handler for this proxy instance.  For Proxy, this
 179:    * field is unused, but it appears here in order to be serialized in all
 180:    * proxy classes.
 181:    *
 182:    * <em>NOTE</em>: This implementation is more secure for proxy classes
 183:    * than what Sun specifies. Sun does not require h to be immutable, but
 184:    * this means you could change h after the fact by reflection.  However,
 185:    * by making h immutable, we may break non-proxy classes which extend
 186:    * Proxy.
 187:    * @serial invocation handler associated with this proxy instance
 188:    */
 189:   protected InvocationHandler h;
 190: 
 191:   /**
 192:    * Constructs a new Proxy from a subclass (usually a proxy class),
 193:    * with the specified invocation handler.
 194:    *
 195:    * <em>NOTE</em>: This throws a NullPointerException if you attempt
 196:    * to create a proxy instance with a null handler using reflection.
 197:    * This behavior is not yet specified by Sun; see Sun Bug 4487672.
 198:    *
 199:    * @param handler the invocation handler, may be null if the subclass
 200:    *        is not a proxy class
 201:    * @throws NullPointerException if handler is null and this is a proxy
 202:    *         instance
 203:    */
 204:   protected Proxy(InvocationHandler handler)
 205:   {
 206:     if (handler == null && isProxyClass(getClass()))
 207:       throw new NullPointerException("invalid handler");
 208:     h = handler;
 209:   }
 210: 
 211:   /**
 212:    * Returns the proxy {@link Class} for the given ClassLoader and array
 213:    * of interfaces, dynamically generating it if necessary.
 214:    *
 215:    * <p>There are several restrictions on this method, the violation of
 216:    * which will result in an IllegalArgumentException or
 217:    * NullPointerException:</p>
 218:    * 
 219:    * <ul>
 220:    * <li>All objects in `interfaces' must represent distinct interfaces.
 221:    *     Classes, primitive types, null, and duplicates are forbidden.</li>
 222:    * <li>The interfaces must be visible in the specified ClassLoader.
 223:    *     In other words, for each interface i:
 224:    *     <code>Class.forName(i.getName(), false, loader) == i</code>
 225:    *     must be true.</li>
 226:    * <li>All non-public interfaces (if any) must reside in the same
 227:    *     package, or the proxy class would be non-instantiable.  If
 228:    *     there are no non-public interfaces, the package of the proxy
 229:    *     class is unspecified.</li>
 230:    * <li>All interfaces must be compatible - if two declare a method
 231:    *     with the same name and parameters, the return type must be
 232:    *     the same and the throws clause of the proxy class will be
 233:    *     the maximal subset of subclasses of the throws clauses for
 234:    *     each method that is overridden.</li>
 235:    * <li>VM constraints limit the number of interfaces a proxy class
 236:    *     may directly implement (however, the indirect inheritance
 237:    *     of {@link Serializable} does not count against this limit).
 238:    *     Even though most VMs can theoretically have 65535
 239:    *     superinterfaces for a class, the actual limit is smaller
 240:    *     because a class's constant pool is limited to 65535 entries,
 241:    *     and not all entries can be interfaces.</li>
 242:    * </ul>
 243:    *
 244:    * <p>Note that different orders of interfaces produce distinct classes.</p>
 245:    *
 246:    * @param loader the class loader to define the proxy class in; null
 247:    *        implies the bootstrap class loader
 248:    * @param interfaces the array of interfaces the proxy class implements,
 249:    *        may be empty, but not null
 250:    * @return the Class object of the proxy class
 251:    * @throws IllegalArgumentException if the constraints above were
 252:    *         violated, except for problems with null
 253:    * @throws NullPointerException if `interfaces' is null or contains
 254:    *         a null entry
 255:    */
 256:   // synchronized so that we aren't trying to build the same class
 257:   // simultaneously in two threads
 258:   public static synchronized Class getProxyClass(ClassLoader loader,
 259:                                                  Class[] interfaces)
 260:   {
 261:     interfaces = (Class[]) interfaces.clone();
 262:     ProxyType pt = new ProxyType(loader, interfaces);
 263:     Class clazz = (Class) proxyClasses.get(pt);
 264:     if (clazz == null)
 265:       {
 266:         if (Configuration.HAVE_NATIVE_GET_PROXY_CLASS)
 267:           clazz = getProxyClass0(loader, interfaces);
 268:         else
 269:           {
 270:             ProxyData data = (Configuration.HAVE_NATIVE_GET_PROXY_DATA
 271:                               ? getProxyData0(loader, interfaces)
 272:                               : ProxyData.getProxyData(pt));
 273: 
 274:             clazz = (Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS
 275:              ? generateProxyClass0(loader, data)
 276:                      : new ClassFactory(data).generate(loader));
 277:           }
 278: 
 279:         Object check = proxyClasses.put(pt, clazz);
 280:         // assert check == null && clazz != null;
 281:         if (check != null || clazz == null)
 282:           throw new InternalError(/*"Fatal flaw in getProxyClass"*/);
 283:       }
 284:     return clazz;
 285:   }
 286: 
 287:   /**
 288:    * Combines several methods into one.  This is equivalent to:
 289:    * <pre>
 290:    *   Proxy.getProxyClass(loader, interfaces)
 291:    *       .getConstructor(new Class[] {InvocationHandler.class})
 292:    *       .newInstance(new Object[] {handler});
 293:    * </pre>
 294:    * except that it will not fail with the normal problems caused
 295:    * by reflection.  It can still fail for the same reasons documented
 296:    * in getProxyClass, or if handler is null.
 297:    *
 298:    * @param loader the class loader to define the proxy class in; null
 299:    *        implies the bootstrap class loader
 300:    * @param interfaces the array of interfaces the proxy class implements,
 301:    *        may be empty, but not null
 302:    * @param handler the invocation handler, may not be null
 303:    * @return a proxy instance implementing the specified interfaces
 304:    * @throws IllegalArgumentException if the constraints for getProxyClass
 305:    *         were violated, except for problems with null
 306:    * @throws NullPointerException if `interfaces' is null or contains
 307:    *         a null entry, or if handler is null
 308:    * @see #getProxyClass(ClassLoader, Class[])
 309:    * @see Class#getConstructor(Class[])
 310:    * @see Constructor#newInstance(Object[])
 311:    */
 312:   public static Object newProxyInstance(ClassLoader loader,
 313:                                         Class[] interfaces,
 314:                                         InvocationHandler handler)
 315:   {
 316:     try
 317:       {
 318:         // getProxyClass() and Proxy() throw the necessary exceptions
 319:         return getProxyClass(loader, interfaces)
 320:           .getConstructor(new Class[] {InvocationHandler.class})
 321:           .newInstance(new Object[] {handler});
 322:       }
 323:     catch (RuntimeException e)
 324:       {
 325:         // Let IllegalArgumentException, NullPointerException escape.
 326:         // assert e instanceof IllegalArgumentException
 327:         //   || e instanceof NullPointerException;
 328:         throw e;
 329:       }
 330:     catch (InvocationTargetException e)
 331:       {
 332:         // Let wrapped NullPointerException escape.
 333:         // assert e.getTargetException() instanceof NullPointerException
 334:         throw (NullPointerException) e.getCause();
 335:       }
 336:     catch (Exception e)
 337:       {
 338:         // Covers InstantiationException, IllegalAccessException,
 339:         // NoSuchMethodException, none of which should be generated
 340:         // if the proxy class was generated correctly.
 341:         // assert false;
 342:         throw (Error) new InternalError("Unexpected: " + e).initCause(e);
 343:       }
 344:   }
 345: 
 346:   /**
 347:    * Returns true if and only if the Class object is a dynamically created
 348:    * proxy class (created by <code>getProxyClass</code> or by the
 349:    * syntactic sugar of <code>newProxyInstance</code>).
 350:    *
 351:    * <p>This check is secure (in other words, it is not simply
 352:    * <code>clazz.getSuperclass() == Proxy.class</code>), it will not
 353:    * be spoofed by non-proxy classes that extend Proxy.
 354:    *
 355:    * @param clazz the class to check, must not be null
 356:    * @return true if the class represents a proxy class
 357:    * @throws NullPointerException if clazz is null
 358:    */
 359:   // This is synchronized on the off chance that another thread is
 360:   // trying to add a class to the map at the same time we read it.
 361:   public static synchronized boolean isProxyClass(Class clazz)
 362:   {
 363:     if (! Proxy.class.isAssignableFrom(clazz))
 364:       return false;
 365:     // This is a linear search, even though we could do an O(1) search
 366:     // using new ProxyType(clazz.getClassLoader(), clazz.getInterfaces()).
 367:     return proxyClasses.containsValue(clazz);
 368:   }
 369: 
 370:   /**
 371:    * Returns the invocation handler for the given proxy instance.<p>
 372:    *
 373:    * <em>NOTE</em>: We guarantee a non-null result if successful,
 374:    * but Sun allows the creation of a proxy instance with a null
 375:    * handler.  See the comments for {@link #Proxy(InvocationHandler)}.
 376:    *
 377:    * @param proxy the proxy instance, must not be null
 378:    * @return the invocation handler, guaranteed non-null.
 379:    * @throws IllegalArgumentException if
 380:    *         <code>Proxy.isProxyClass(proxy.getClass())</code> returns false.
 381:    * @throws NullPointerException if proxy is null
 382:    */
 383:   public static InvocationHandler getInvocationHandler(Object proxy)
 384:   {
 385:     if (! isProxyClass(proxy.getClass()))
 386:       throw new IllegalArgumentException("not a proxy instance");
 387:     return ((Proxy) proxy).h;
 388:   }
 389: 
 390:   /**
 391:    * Optional native method to replace (and speed up) the pure Java
 392:    * implementation of getProxyClass.  Only needed if
 393:    * Configuration.HAVE_NATIVE_GET_PROXY_CLASS is true, this does the
 394:    * work of both getProxyData0 and generateProxyClass0 with no
 395:    * intermediate form in Java. The native code may safely assume that
 396:    * this class must be created, and does not already exist.
 397:    *
 398:    * @param loader the class loader to define the proxy class in; null
 399:    *        implies the bootstrap class loader
 400:    * @param interfaces the interfaces the class will extend
 401:    * @return the generated proxy class
 402:    * @throws IllegalArgumentException if the constraints for getProxyClass
 403:    *         were violated, except for problems with null
 404:    * @throws NullPointerException if `interfaces' is null or contains
 405:    *         a null entry, or if handler is null
 406:    * @see Configuration#HAVE_NATIVE_GET_PROXY_CLASS
 407:    * @see #getProxyClass(ClassLoader, Class[])
 408:    * @see #getProxyData0(ClassLoader, Class[])
 409:    * @see #generateProxyClass0(ProxyData)
 410:    */
 411:   private static native Class getProxyClass0(ClassLoader loader,
 412:                                              Class[] interfaces);
 413: 
 414:   /**
 415:    * Optional native method to replace (and speed up) the pure Java
 416:    * implementation of getProxyData.  Only needed if
 417:    * Configuration.HAVE_NATIVE_GET_PROXY_DATA is true. The native code
 418:    * may safely assume that a new ProxyData object must be created which
 419:    * does not duplicate any existing ones.
 420:    *
 421:    * @param loader the class loader to define the proxy class in; null
 422:    *        implies the bootstrap class loader
 423:    * @param interfaces the interfaces the class will extend
 424:    * @return all data that is required to make this proxy class
 425:    * @throws IllegalArgumentException if the constraints for getProxyClass
 426:    *         were violated, except for problems with null
 427:    * @throws NullPointerException if `interfaces' is null or contains
 428:    *         a null entry, or if handler is null
 429:    * @see Configuration.HAVE_NATIVE_GET_PROXY_DATA
 430:    * @see #getProxyClass(ClassLoader, Class[])
 431:    * @see #getProxyClass0(ClassLoader, Class[])
 432:    * @see ProxyType#getProxyData()
 433:    */
 434:   private static native ProxyData getProxyData0(ClassLoader loader,
 435:                                                 Class[] interfaces);
 436: 
 437:   /**
 438:    * Optional native method to replace (and speed up) the pure Java
 439:    * implementation of generateProxyClass.  Only needed if
 440:    * Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS is true. The native
 441:    * code may safely assume that a new Class must be created, and that
 442:    * the ProxyData object does not describe any existing class.
 443:    *
 444:    * @param loader the class loader to define the proxy class in; null
 445:    *        implies the bootstrap class loader
 446:    * @param data the struct of information to convert to a Class. This
 447:    *        has already been verified for all problems except exceeding
 448:    *        VM limitations
 449:    * @return the newly generated class
 450:    * @throws IllegalArgumentException if VM limitations are exceeded
 451:    * @see #getProxyClass(ClassLoader, Class[])
 452:    * @see #getProxyClass0(ClassLoader, Class[])
 453:    * @see ProxyData#generateProxyClass(ClassLoader)
 454:    */
 455:   private static native Class generateProxyClass0(ClassLoader loader,
 456:                                                   ProxyData data);
 457: 
 458:   /**
 459:    * Helper class for mapping unique ClassLoader and interface combinations
 460:    * to proxy classes.
 461:    *
 462:    * @author Eric Blake (ebb9@email.byu.edu)
 463:    */
 464:   private static final class ProxyType
 465:   {
 466:     /**
 467:      * Store the class loader (may be null)
 468:      */
 469:     final ClassLoader loader;
 470: 
 471:     /**
 472:      * Store the interfaces (never null, all elements are interfaces)
 473:      */
 474:     final Class[] interfaces;
 475: 
 476:     /**
 477:      * Construct the helper object.
 478:      *
 479:      * @param loader the class loader to define the proxy class in; null
 480:      *        implies the bootstrap class loader
 481:      * @param interfaces an array of interfaces
 482:      */
 483:     ProxyType(ClassLoader loader, Class[] interfaces)
 484:     {
 485:       if (loader == null)
 486:          loader = ClassLoader.getSystemClassLoader();
 487:       this.loader = loader;
 488:       this.interfaces = interfaces;
 489:     }
 490: 
 491:     /**
 492:      * Calculates the hash code.
 493:      *
 494:      * @return a combination of the classloader and interfaces hashcodes.
 495:      */
 496:     public int hashCode()
 497:     {
 498:       //loader is always not null
 499:       int hash = loader.hashCode();
 500:       for (int i = 0; i < interfaces.length; i++)
 501:         hash = hash * 31 + interfaces[i].hashCode();
 502:       return hash;
 503:     }
 504: 
 505:     // A more comprehensive comparison of two arrays,
 506:     //   ignore array element order, and
 507:     //   ignore redundant elements
 508:     private static boolean sameTypes(Class arr1[], Class arr2[]) {
 509:       if (arr1.length == 1 && arr2.length == 1) {
 510:         return arr1[0] == arr2[0];
 511:       }
 512:         
 513:       // total occurrance of elements of arr1 in arr2
 514:       int total_occ_of_arr1_in_arr2 = 0;
 515:     each_type:
 516:       for (int i = arr1.length; --i >= 0; ) 
 517:       {
 518:         Class t = arr1[i];
 519:         for (int j = i; --j >= 0; ) 
 520:         {
 521:           if (t == arr1[j]) 
 522:           { //found duplicate type
 523:             continue each_type;  
 524:           }
 525:         }
 526:             
 527:         // count c(a unique element of arr1)'s 
 528:         //   occurrences in arr2
 529:         int occ_in_arr2 = 0;
 530:         for (int j = arr2.length; --j >= 0; ) 
 531:         {
 532:           if (t == arr2[j]) 
 533:           {
 534:             ++occ_in_arr2;
 535:           }
 536:         }
 537:         if (occ_in_arr2 == 0) 
 538:         { // t does not occur in arr2
 539:           return false;
 540:         }
 541:         
 542:         total_occ_of_arr1_in_arr2 += occ_in_arr2;
 543:       }
 544:       // now, each element of arr2 must have been visited
 545:       return total_occ_of_arr1_in_arr2 == arr2.length;
 546:     }
 547: 
 548:     /**
 549:      * Calculates equality.
 550:      *
 551:      * @param the object to compare to
 552:      * @return true if it is a ProxyType with same data
 553:      */
 554:     public boolean equals(Object other)
 555:     {
 556:       ProxyType pt = (ProxyType) other;
 557:       if (loader != pt.loader || interfaces.length != pt.interfaces.length)
 558:         return false;
 559:       return sameTypes(interfaces, pt.interfaces);
 560:     }
 561:   } // class ProxyType
 562: 
 563:   /**
 564:    * Helper class which allows hashing of a method name and signature
 565:    * without worrying about return type, declaring class, or throws clause,
 566:    * and which reduces the maximally common throws clause between two methods
 567:    *
 568:    * @author Eric Blake (ebb9@email.byu.edu)
 569:    */
 570:   private static final class ProxySignature
 571:   {
 572:     /**
 573:      * The core signatures which all Proxy instances handle.
 574:      */
 575:     static final HashMap coreMethods = new HashMap();
 576:     static
 577:     {
 578:       try
 579:         {
 580:           ProxySignature sig
 581:             = new ProxySignature(Object.class
 582:                                  .getMethod("equals",
 583:                                             new Class[] {Object.class}));
 584:           coreMethods.put(sig, sig);
 585:           sig = new ProxySignature(Object.class.getMethod("hashCode", null));
 586:           coreMethods.put(sig, sig);
 587:           sig = new ProxySignature(Object.class.getMethod("toString", null));
 588:           coreMethods.put(sig, sig);
 589:         }
 590:       catch (Exception e)
 591:         {
 592:           // assert false;
 593:           throw (Error) new InternalError("Unexpected: " + e).initCause(e);
 594:         }
 595:     }
 596: 
 597:     /**
 598:      * The underlying Method object, never null
 599:      */
 600:     final Method method;
 601: 
 602:     /**
 603:      * The set of compatible thrown exceptions, may be empty
 604:      */
 605:     final Set exceptions = new HashSet();
 606: 
 607:     /**
 608:      * Construct a signature
 609:      *
 610:      * @param method the Method this signature is based on, never null
 611:      */
 612:     ProxySignature(Method method)
 613:     {
 614:       this.method = method;
 615:       Class[] exc = method.getExceptionTypes();
 616:       int i = exc.length;
 617:       while (--i >= 0)
 618:         {
 619:           // discard unchecked exceptions
 620:           if (Error.class.isAssignableFrom(exc[i])
 621:               || RuntimeException.class.isAssignableFrom(exc[i]))
 622:             continue;
 623:           exceptions.add(exc[i]);
 624:         }
 625:     }
 626: 
 627:     /**
 628:      * Given a method, make sure it's return type is identical
 629:      * to this, and adjust this signature's throws clause appropriately
 630:      *
 631:      * @param other the signature to merge in
 632:      * @throws IllegalArgumentException if the return types conflict
 633:      */
 634:     void checkCompatibility(ProxySignature other)
 635:     {
 636:       if (method.getReturnType() != other.method.getReturnType())
 637:         throw new IllegalArgumentException("incompatible return types: "
 638:                                            + method + ", " + other.method);
 639: 
 640:       // if you can think of a more efficient way than this O(n^2) search,
 641:       // implement it!
 642:       int size1 = exceptions.size();
 643:       int size2 = other.exceptions.size();
 644:       boolean[] valid1 = new boolean[size1];
 645:       boolean[] valid2 = new boolean[size2];
 646:       Iterator itr = exceptions.iterator();
 647:       int pos = size1;
 648:       while (--pos >= 0)
 649:         {
 650:           Class c1 = (Class) itr.next();
 651:           Iterator itr2 = other.exceptions.iterator();
 652:           int pos2 = size2;
 653:           while (--pos2 >= 0)
 654:             {
 655:               Class c2 = (Class) itr2.next();
 656:               if (c2.isAssignableFrom(c1))
 657:                 valid1[pos] = true;
 658:               if (c1.isAssignableFrom(c2))
 659:                 valid2[pos2] = true;
 660:             }
 661:         }
 662:       pos = size1;
 663:       itr = exceptions.iterator();
 664:       while (--pos >= 0)
 665:         {
 666:           itr.next();
 667:           if (! valid1[pos])
 668:             itr.remove();
 669:         }
 670:       pos = size2;
 671:       itr = other.exceptions.iterator();
 672:       while (--pos >= 0)
 673:         {
 674:           itr.next();
 675:           if (! valid2[pos])
 676:             itr.remove();
 677:         }
 678:       exceptions.addAll(other.exceptions);
 679:     }
 680: 
 681:     /**
 682:      * Calculates the hash code.
 683:      *
 684:      * @return a combination of name and parameter types
 685:      */
 686:     public int hashCode()
 687:     {
 688:       int hash = method.getName().hashCode();
 689:       Class[] types = method.getParameterTypes();
 690:       for (int i = 0; i < types.length; i++)
 691:         hash = hash * 31 + types[i].hashCode();
 692:       return hash;
 693:     }
 694: 
 695:     /**
 696:      * Calculates equality.
 697:      *
 698:      * @param the object to compare to
 699:      * @return true if it is a ProxySignature with same data
 700:      */
 701:     public boolean equals(Object other)
 702:     {
 703:       ProxySignature ps = (ProxySignature) other;
 704:       Class[] types1 = method.getParameterTypes();
 705:       Class[] types2 = ps.method.getParameterTypes();
 706:       if (! method.getName().equals(ps.method.getName())
 707:           || types1.length != types2.length)
 708:         return false;
 709:       int i = types1.length;
 710:       while (--i >= 0)
 711:         if (types1[i] != types2[i])
 712:           return false;
 713:       return true;
 714:     }
 715:   } // class ProxySignature
 716: 
 717:   /**
 718:    * A flat representation of all data needed to generate bytecode/instantiate
 719:    * a proxy class.  This is basically a struct.
 720:    *
 721:    * @author Eric Blake (ebb9@email.byu.edu)
 722:    */
 723:   private static final class ProxyData
 724:   {
 725:     /**
 726:      * The package this class is in <b>including the trailing dot</b>
 727:      * or an empty string for the unnamed (aka default) package.
 728:      */
 729:     String pack;
 730: 
 731:     /**
 732:      * The interfaces this class implements.  Non-null, but possibly empty.
 733:      */
 734:     Class[] interfaces;
 735: 
 736:     /**
 737:      * The Method objects this class must pass as the second argument to
 738:      * invoke (also useful for determining what methods this class has).
 739:      * Non-null, non-empty (includes at least Object.hashCode, Object.equals,
 740:      * and Object.toString).
 741:      */
 742:     Method[] methods;
 743: 
 744:     /**
 745:      * The exceptions that do not need to be wrapped in
 746:      * UndeclaredThrowableException. exceptions[i] is the same as, or a
 747:      * subset of subclasses, of methods[i].getExceptionTypes(), depending on
 748:      * compatible throws clauses with multiple inheritance. It is unspecified
 749:      * if these lists include or exclude subclasses of Error and
 750:      * RuntimeException, but excluding them is harmless and generates a
 751:      * smaller class.
 752:      */
 753:     Class[][] exceptions;
 754: 
 755:     /**
 756:      * For unique id's
 757:      */
 758:     private static int count;
 759: 
 760:     /**
 761:      * The id of this proxy class
 762:      */
 763:     final int id = count++;
 764: 
 765:     /**
 766:      * Construct a ProxyData with uninitialized data members.
 767:      */
 768:     ProxyData()
 769:     {
 770:     }
 771: 
 772:     /**
 773:      * Return the name of a package (including the trailing dot)
 774:      * given the name of a class.
 775:      * Returns an empty string if no package.  We use this in preference to
 776:      * using Class.getPackage() to avoid problems with ClassLoaders
 777:      * that don't set the package.
 778:      */
 779:     private static String getPackage(Class k)
 780:     {
 781:       String name = k.getName();
 782:       int idx = name.lastIndexOf('.');
 783:       return name.substring(0, idx + 1);
 784:     }
 785: 
 786:     /**
 787:      * Verifies that the arguments are legal, and sets up remaining data
 788:      * This should only be called when a class must be generated, as
 789:      * it is expensive.
 790:      *
 791:      * @param pt the ProxyType to convert to ProxyData
 792:      * @return the flattened, verified ProxyData structure for use in
 793:      *         class generation
 794:      * @throws IllegalArgumentException if `interfaces' contains
 795:      *         non-interfaces or incompatible combinations, and verify is true
 796:      * @throws NullPointerException if interfaces is null or contains null
 797:      */
 798:     static ProxyData getProxyData(ProxyType pt)
 799:     {
 800:       Map method_set = (Map) ProxySignature.coreMethods.clone();
 801:       boolean in_package = false; // true if we encounter non-public interface
 802: 
 803:       ProxyData data = new ProxyData();
 804:       data.interfaces = pt.interfaces;
 805: 
 806:       // if interfaces is too large, we croak later on when the constant
 807:       // pool overflows
 808:       int i = data.interfaces.length;
 809:       while (--i >= 0)
 810:         {
 811:           Class inter = data.interfaces[i];
 812:           if (! inter.isInterface())
 813:             throw new IllegalArgumentException("not an interface: " + inter);
 814:           try
 815:             {
 816:               if (Class.forName(inter.getName(), false, pt.loader) != inter)
 817:                 throw new IllegalArgumentException("not accessible in "
 818:                                                    + "classloader: " + inter);
 819:             }
 820:           catch (ClassNotFoundException e)
 821:             {
 822:               throw new IllegalArgumentException("not accessible in "
 823:                                                  + "classloader: " + inter);
 824:             }
 825:           if (! Modifier.isPublic(inter.getModifiers()))
 826:             if (in_package)
 827:               {
 828:         String p = getPackage(inter);
 829:                 if (! data.pack.equals(p))
 830:                   throw new IllegalArgumentException("non-public interfaces "
 831:                                                      + "from different "
 832:                                                      + "packages");
 833:               }
 834:             else
 835:               {
 836:                 in_package = true;
 837:                 data.pack = getPackage(inter);
 838:               }
 839:           for (int j = i-1; j >= 0; j--)
 840:             if (data.interfaces[j] == inter)
 841:               throw new IllegalArgumentException("duplicate interface: "
 842:                                                  + inter);
 843:           Method[] methods = inter.getMethods();
 844:           int j = methods.length;
 845:           while (--j >= 0)
 846:             {
 847:               ProxySignature sig = new ProxySignature(methods[j]);
 848:               ProxySignature old = (ProxySignature) method_set.put(sig, sig);
 849:               if (old != null)
 850:                 sig.checkCompatibility(old);
 851:             }
 852:         }
 853: 
 854:       i = method_set.size();
 855:       data.methods = new Method[i];
 856:       data.exceptions = new Class[i][];
 857:       Iterator itr = method_set.values().iterator();
 858:       while (--i >= 0)
 859:         {
 860:           ProxySignature sig = (ProxySignature) itr.next();
 861:           data.methods[i] = sig.method;
 862:           data.exceptions[i] = (Class[]) sig.exceptions
 863:             .toArray(new Class[sig.exceptions.size()]);
 864:         }
 865:       return data;
 866:     }
 867:   } // class ProxyData
 868: 
 869:   /**
 870:    * Does all the work of building a class. By making this a nested class,
 871:    * this code is not loaded in memory if the VM has a native
 872:    * implementation instead.
 873:    *
 874:    * @author Eric Blake (ebb9@email.byu.edu)
 875:    */
 876:   private static final class ClassFactory
 877:   {
 878:     /** Constants for assisting the compilation */
 879:     private static final byte POOL = 0;
 880:     private static final byte FIELD = 1;
 881:     private static final byte METHOD = 2;
 882:     private static final byte INTERFACE = 3;
 883:     private static final String CTOR_SIG
 884:       = "(Ljava/lang/reflect/InvocationHandler;)V";
 885:     private static final String INVOKE_SIG = "(Ljava/lang/Object;"
 886:       + "Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";
 887: 
 888:     /** Bytecodes for insertion in the class definition byte[] */
 889:     private static final char ACONST_NULL = 1;
 890:     private static final char ICONST_0 = 3;
 891:     private static final char BIPUSH = 16;
 892:     private static final char SIPUSH = 17;
 893:     private static final char ILOAD = 21;
 894:     private static final char ILOAD_0 = 26;
 895:     private static final char ALOAD_0 = 42;
 896:     private static final char ALOAD_1 = 43;
 897:     private static final char AALOAD = 50;
 898:     private static final char AASTORE = 83;
 899:     private static final char DUP = 89;
 900:     private static final char DUP_X1 = 90;
 901:     private static final char SWAP = 95;
 902:     private static final char IRETURN = 172;
 903:     private static final char LRETURN = 173;
 904:     private static final char FRETURN = 174;
 905:     private static final char DRETURN = 175;
 906:     private static final char ARETURN = 176;
 907:     private static final char RETURN = 177;
 908:     private static final char GETSTATIC = 178;
 909:     private static final char GETFIELD = 180;
 910:     private static final char INVOKEVIRTUAL = 182;
 911:     private static final char INVOKESPECIAL = 183;
 912:     private static final char INVOKESTATIC = 184;
 913:     private static final char INVOKEINTERFACE = 185;
 914:     private static final char NEW = 187;
 915:     private static final char ANEWARRAY = 189;
 916:     private static final char ATHROW = 191;
 917:     private static final char CHECKCAST = 192;
 918: 
 919:     // Implementation note: we use StringBuffers to hold the byte data, since
 920:     // they automatically grow.  However, we only use the low 8 bits of
 921:     // every char in the array, so we are using twice the necessary memory
 922:     // for the ease StringBuffer provides.
 923: 
 924:     /** The constant pool. */
 925:     private final StringBuffer pool = new StringBuffer();
 926:     /** The rest of the class data. */
 927:     private final StringBuffer stream = new StringBuffer();
 928: 
 929:     /** Map of strings to byte sequences, to minimize size of pool. */
 930:     private final Map poolEntries = new HashMap();
 931: 
 932:     /** The VM name of this proxy class. */
 933:     private final String qualName;
 934: 
 935:     /**
 936:      * The Method objects the proxy class refers to when calling the
 937:      * invocation handler.
 938:      */
 939:     private final Method[] methods;
 940: 
 941:     /**
 942:      * Initializes the buffers with the bytecode contents for a proxy class.
 943:      *
 944:      * @param data the remainder of the class data
 945:      * @throws IllegalArgumentException if anything else goes wrong this
 946:      *         late in the game; as far as I can tell, this will only happen
 947:      *         if the constant pool overflows, which is possible even when
 948:      *         the user doesn't exceed the 65535 interface limit
 949:      */
 950:     ClassFactory(ProxyData data)
 951:     {
 952:       methods = data.methods;
 953: 
 954:       // magic = 0xcafebabe
 955:       // minor_version = 0
 956:       // major_version = 46
 957:       // constant_pool_count: place-holder for now
 958:       pool.append("\u00ca\u00fe\u00ba\u00be\0\0\0\56\0\0");
 959:       // constant_pool[], filled in as we go
 960: 
 961:       // access_flags
 962:       putU2(Modifier.SUPER | Modifier.FINAL | Modifier.PUBLIC);
 963:       // this_class
 964:       qualName = (data.pack + "$Proxy" + data.id);
 965:       putU2(classInfo(TypeSignature.getEncodingOfClass(qualName, false)));
 966:       // super_class
 967:       putU2(classInfo("java/lang/reflect/Proxy"));
 968: 
 969:       // interfaces_count
 970:       putU2(data.interfaces.length);
 971:       // interfaces[]
 972:       for (int i = 0; i < data.interfaces.length; i++)
 973:         putU2(classInfo(data.interfaces[i]));
 974: 
 975:       // Recall that Proxy classes serialize specially, so we do not need
 976:       // to worry about a <clinit> method for this field.  Instead, we
 977:       // just assign it by reflection after the class is successfully loaded.
 978:       // fields_count - private static Method[] m;
 979:       putU2(1);
 980:       // fields[]
 981:       // m.access_flags
 982:       putU2(Modifier.PRIVATE | Modifier.STATIC);
 983:       // m.name_index
 984:       putU2(utf8Info("m"));
 985:       // m.descriptor_index
 986:       putU2(utf8Info("[Ljava/lang/reflect/Method;"));
 987:       // m.attributes_count
 988:       putU2(0);
 989:       // m.attributes[]
 990: 
 991:       // methods_count - # handler methods, plus <init>
 992:       putU2(methods.length + 1);
 993:       // methods[]
 994:       // <init>.access_flags
 995:       putU2(Modifier.PUBLIC);
 996:       // <init>.name_index
 997:       putU2(utf8Info("<init>"));
 998:       // <init>.descriptor_index
 999:       putU2(utf8Info(CTOR_SIG));
1000:       // <init>.attributes_count - only Code is needed
1001:       putU2(1);
1002:       // <init>.Code.attribute_name_index
1003:       putU2(utf8Info("Code"));
1004:       // <init>.Code.attribute_length = 18
1005:       // <init>.Code.info:
1006:       //   $Proxynn(InvocationHandler h) { super(h); }
1007:       // <init>.Code.max_stack = 2
1008:       // <init>.Code.max_locals = 2
1009:       // <init>.Code.code_length = 6
1010:       // <init>.Code.code[]
1011:       stream.append("\0\0\0\22\0\2\0\2\0\0\0\6" + ALOAD_0 + ALOAD_1
1012:                     + INVOKESPECIAL);
1013:       putU2(refInfo(METHOD, "java/lang/reflect/Proxy", "<init>", CTOR_SIG));
1014:       // <init>.Code.exception_table_length = 0
1015:       // <init>.Code.exception_table[]
1016:       // <init>.Code.attributes_count = 0
1017:       // <init>.Code.attributes[]
1018:       stream.append(RETURN + "\0\0\0\0");
1019: 
1020:       for (int i = methods.length - 1; i >= 0; i--)
1021:         emitMethod(i, data.exceptions[i]);
1022: 
1023:       // attributes_count
1024:       putU2(0);
1025:       // attributes[] - empty; omit SourceFile attribute
1026:       // XXX should we mark this with a Synthetic attribute?
1027:     }
1028: 
1029:     /**
1030:      * Produce the bytecode for a single method.
1031:      *
1032:      * @param i the index of the method we are building
1033:      * @param e the exceptions possible for the method
1034:      */
1035:     private void emitMethod(int i, Class[] e)
1036:     {
1037:       // First, we precalculate the method length and other information.
1038: 
1039:       Method m = methods[i];
1040:       Class[] paramtypes = m.getParameterTypes();
1041:       int wrap_overhead = 0; // max words taken by wrapped primitive
1042:       int param_count = 1; // 1 for this
1043:       int code_length = 16; // aload_0, getfield, aload_0, getstatic, const,
1044:       // aaload, const/aconst_null, invokeinterface
1045:       if (i > 5)
1046:         {
1047:           if (i > Byte.MAX_VALUE)
1048:             code_length += 2; // sipush
1049:           else
1050:             code_length++; // bipush
1051:         }
1052:       if (paramtypes.length > 0)
1053:         {
1054:           code_length += 3; // anewarray
1055:           if (paramtypes.length > Byte.MAX_VALUE)
1056:             code_length += 2; // sipush
1057:           else if (paramtypes.length > 5)
1058:             code_length++; // bipush
1059:           for (int j = 0; j < paramtypes.length; j++)
1060:             {
1061:               code_length += 4; // dup, const, load, store
1062:               Class type = paramtypes[j];
1063:               if (j > 5)
1064:                 {
1065:                   if (j > Byte.MAX_VALUE)
1066:                     code_length += 2; // sipush
1067:                   else
1068:                     code_length++; // bipush
1069:                 }
1070:               if (param_count >= 4)
1071:                 code_length++; // 2-byte load
1072:               param_count++;
1073:               if (type.isPrimitive())
1074:                 {
1075:                   code_length += 7; // new, dup, invokespecial
1076:                   if (type == long.class || type == double.class)
1077:                     {
1078:                       wrap_overhead = 3;
1079:                       param_count++;
1080:                     }
1081:                   else if (wrap_overhead < 2)
1082:                     wrap_overhead = 2;
1083:                 }
1084:             }
1085:         }
1086:       int end_pc = code_length;
1087:       Class ret_type = m.getReturnType();
1088:       if (ret_type == void.class)
1089:         code_length++; // return
1090:       else if (ret_type.isPrimitive())
1091:         code_length += 7; // cast, invokevirtual, return
1092:       else
1093:         code_length += 4; // cast, return
1094:       int exception_count = 0;
1095:       boolean throws_throwable = false;
1096:       for (int j = 0; j < e.length; j++)
1097:         if (e[j] == Throwable.class)
1098:           {
1099:             throws_throwable = true;
1100:             break;
1101:           }
1102:       if (! throws_throwable)
1103:         {
1104:           exception_count = e.length + 3; // Throwable, Error, RuntimeException
1105:           code_length += 9; // new, dup_x1, swap, invokespecial, athrow
1106:         }
1107:       int handler_pc = code_length - 1;
1108:       StringBuffer signature = new StringBuffer("(");
1109:       for (int j = 0; j < paramtypes.length; j++)
1110:         signature.append(TypeSignature.getEncodingOfClass(paramtypes[j]));
1111:       signature.append(")").append(TypeSignature.getEncodingOfClass(ret_type));
1112: 
1113:       // Now we have enough information to emit the method.
1114: 
1115:       // handler.access_flags
1116:       putU2(Modifier.PUBLIC | Modifier.FINAL);
1117:       // handler.name_index
1118:       putU2(utf8Info(m.getName()));
1119:       // handler.descriptor_index
1120:       putU2(utf8Info(signature.toString()));
1121:       // handler.attributes_count - Code is necessary, Exceptions possible
1122:       putU2(e.length > 0 ? 2 : 1);
1123: 
1124:       // handler.Code.info:
1125:       //   type name(args) {
1126:       //     try {
1127:       //       return (type) h.invoke(this, methods[i], new Object[] {args});
1128:       //     } catch (<declared Exceptions> e) {
1129:       //       throw e;
1130:       //     } catch (Throwable t) {
1131:       //       throw new UndeclaredThrowableException(t);
1132:       //     }
1133:       //   }
1134:       // Special cases:
1135:       //  if arg_n is primitive, wrap it
1136:       //  if method throws Throwable, try-catch is not needed
1137:       //  if method returns void, return statement not needed
1138:       //  if method returns primitive, unwrap it
1139:       //  save space by sharing code for all the declared handlers
1140: 
1141:       // handler.Code.attribute_name_index
1142:       putU2(utf8Info("Code"));
1143:       // handler.Code.attribute_length
1144:       putU4(12 + code_length + 8 * exception_count);
1145:       // handler.Code.max_stack
1146:       putU2(param_count == 1 ? 4 : 7 + wrap_overhead);
1147:       // handler.Code.max_locals
1148:       putU2(param_count);
1149:       // handler.Code.code_length
1150:       putU4(code_length);
1151:       // handler.Code.code[]
1152:       putU1(ALOAD_0);
1153:       putU1(GETFIELD);
1154:       putU2(refInfo(FIELD, "java/lang/reflect/Proxy", "h",
1155:                     "Ljava/lang/reflect/InvocationHandler;"));
1156:       putU1(ALOAD_0);
1157:       putU1(GETSTATIC);
1158:       putU2(refInfo(FIELD, TypeSignature.getEncodingOfClass(qualName, false),
1159:                     "m", "[Ljava/lang/reflect/Method;"));
1160:       putConst(i);
1161:       putU1(AALOAD);
1162:       if (paramtypes.length > 0)
1163:         {
1164:           putConst(paramtypes.length);
1165:           putU1(ANEWARRAY);
1166:           putU2(classInfo("java/lang/Object"));
1167:           param_count = 1;
1168:           for (int j = 0; j < paramtypes.length; j++, param_count++)
1169:             {
1170:               putU1(DUP);
1171:               putConst(j);
1172:               if (paramtypes[j].isPrimitive())
1173:                 {
1174:                   putU1(NEW);
1175:                   putU2(classInfo(wrapper(paramtypes[j])));
1176:                   putU1(DUP);
1177:                 }
1178:               putLoad(param_count, paramtypes[j]);
1179:               if (paramtypes[j].isPrimitive())
1180:                 {
1181:                   putU1(INVOKESPECIAL);
1182:                   putU2(refInfo(METHOD, wrapper(paramtypes[j]), "<init>",
1183:                                 '(' + (TypeSignature
1184:                                        .getEncodingOfClass(paramtypes[j])
1185:                                        + ")V")));
1186:                   if (paramtypes[j] == long.class
1187:                       || paramtypes[j] == double.class)
1188:                     param_count++;
1189:                 }
1190:               putU1(AASTORE);
1191:             }
1192:         }
1193:       else
1194:         putU1(ACONST_NULL);
1195:       putU1(INVOKEINTERFACE);
1196:       putU2(refInfo(INTERFACE, "java/lang/reflect/InvocationHandler",
1197:                     "invoke", INVOKE_SIG));
1198:       putU1(4); // InvocationHandler, this, Method, Object[]
1199:       putU1(0);
1200:       if (ret_type == void.class)
1201:         putU1(RETURN);
1202:       else if (ret_type.isPrimitive())
1203:         {
1204:           putU1(CHECKCAST);
1205:           putU2(classInfo(wrapper(ret_type)));
1206:           putU1(INVOKEVIRTUAL);
1207:           putU2(refInfo(METHOD, wrapper(ret_type),
1208:                         ret_type.getName() + "Value",
1209:                         "()" + TypeSignature.getEncodingOfClass(ret_type)));
1210:           if (ret_type == long.class)
1211:             putU1(LRETURN);
1212:           else if (ret_type == float.class)
1213:             putU1(FRETURN);
1214:           else if (ret_type == double.class)
1215:             putU1(DRETURN);
1216:           else
1217:             putU1(IRETURN);
1218:         }
1219:       else
1220:         {
1221:           putU1(CHECKCAST);
1222:           putU2(classInfo(ret_type));
1223:           putU1(ARETURN);
1224:         }
1225:       if (! throws_throwable)
1226:         {
1227:           putU1(NEW);
1228:           putU2(classInfo("java/lang/reflect/UndeclaredThrowableException"));
1229:           putU1(DUP_X1);
1230:           putU1(SWAP);
1231:           putU1(INVOKESPECIAL);
1232:           putU2(refInfo(METHOD,
1233:                         "java/lang/reflect/UndeclaredThrowableException",
1234:                         "<init>", "(Ljava/lang/Throwable;)V"));
1235:           putU1(ATHROW);
1236:         }
1237: 
1238:       // handler.Code.exception_table_length
1239:       putU2(exception_count);
1240:       // handler.Code.exception_table[]
1241:       if (! throws_throwable)
1242:         {
1243:           // handler.Code.exception_table.start_pc
1244:           putU2(0);
1245:           // handler.Code.exception_table.end_pc
1246:           putU2(end_pc);
1247:           // handler.Code.exception_table.handler_pc
1248:           putU2(handler_pc);
1249:           // handler.Code.exception_table.catch_type
1250:           putU2(classInfo("java/lang/Error"));
1251:           // handler.Code.exception_table.start_pc
1252:           putU2(0);
1253:           // handler.Code.exception_table.end_pc
1254:           putU2(end_pc);
1255:           // handler.Code.exception_table.handler_pc
1256:           putU2(handler_pc);
1257:           // handler.Code.exception_table.catch_type
1258:           putU2(classInfo("java/lang/RuntimeException"));
1259:           for (int j = 0; j < e.length; j++)
1260:             {
1261:               // handler.Code.exception_table.start_pc
1262:               putU2(0);
1263:               // handler.Code.exception_table.end_pc
1264:               putU2(end_pc);
1265:               // handler.Code.exception_table.handler_pc
1266:               putU2(handler_pc);
1267:               // handler.Code.exception_table.catch_type
1268:               putU2(classInfo(e[j]));
1269:             }
1270:           // handler.Code.exception_table.start_pc
1271:           putU2(0);
1272:           // handler.Code.exception_table.end_pc
1273:           putU2(end_pc);
1274:           // handler.Code.exception_table.handler_pc -
1275:           //   -8 for undeclared handler, which falls thru to normal one
1276:           putU2(handler_pc - 8);
1277:           // handler.Code.exception_table.catch_type
1278:           putU2(0);
1279:         }
1280:       // handler.Code.attributes_count
1281:       putU2(0);
1282:       // handler.Code.attributes[]
1283: 
1284:       if (e.length > 0)
1285:         {
1286:           // handler.Exceptions.attribute_name_index
1287:           putU2(utf8Info("Exceptions"));
1288:           // handler.Exceptions.attribute_length
1289:           putU4(2 * e.length + 2);
1290:           // handler.Exceptions.number_of_exceptions
1291:           putU2(e.length);
1292:           // handler.Exceptions.exception_index_table[]
1293:           for (int j = 0; j < e.length; j++)
1294:             putU2(classInfo(e[j]));
1295:         }
1296:     }
1297: 
1298:     /**
1299:      * Creates the Class object that corresponds to the bytecode buffers
1300:      * built when this object was constructed.
1301:      *
1302:      * @param loader the class loader to define the proxy class in; null
1303:      *        implies the bootstrap class loader
1304:      * @return the proxy class Class object
1305:      */
1306:     Class generate(ClassLoader loader)
1307:     {
1308:       byte[] bytecode = new byte[pool.length() + stream.length()];
1309:       // More efficient to bypass calling charAt() repetitively.
1310:       char[] c = pool.toString().toCharArray();
1311:       int i = c.length;
1312:       while (--i >= 0)
1313:         bytecode[i] = (byte) c[i];
1314:       c = stream.toString().toCharArray();
1315:       i = c.length;
1316:       int j = bytecode.length;
1317:       while (i > 0)
1318:         bytecode[--j] = (byte) c[--i];
1319: 
1320:       // Patch the constant pool size, which we left at 0 earlier.
1321:       int count = poolEntries.size() + 1;
1322:       bytecode[8] = (byte) (count >> 8);
1323:       bytecode[9] = (byte) count;
1324: 
1325:       try
1326:         {
1327:           Class vmClassLoader = Class.forName("java.lang.VMClassLoader");
1328:           Class[] types = {ClassLoader.class, String.class,
1329:                            byte[].class, int.class, int.class,
1330:                            ProtectionDomain.class };
1331:           Method m = vmClassLoader.getDeclaredMethod("defineClass", types);
1332:           // We can bypass the security check of setAccessible(true), since
1333:       // we're in the same package.
1334:           m.flag = true;
1335: 
1336:           Object[] args = {loader, qualName, bytecode, new Integer(0),
1337:                            new Integer(bytecode.length),
1338:                            Object.class.getProtectionDomain() };
1339:           Class clazz = (Class) m.invoke(null, args);
1340: 
1341:           // Finally, initialize the m field of the proxy class, before
1342:           // returning it.
1343:           Field f = clazz.getDeclaredField("m");
1344:           f.flag = true;
1345:           // we can share the array, because it is not publicized
1346:           f.set(null, methods);
1347: 
1348:           return clazz;
1349:         }
1350:       catch (Exception e)
1351:         {
1352:           // assert false;
1353:           throw (Error) new InternalError("Unexpected: " + e).initCause(e);
1354:         }
1355:     }
1356: 
1357:     /**
1358:      * Put a single byte on the stream.
1359:      *
1360:      * @param i the information to add (only lowest 8 bits are used)
1361:      */
1362:     private void putU1(int i)
1363:     {
1364:       stream.append((char) i);
1365:     }
1366: 
1367:     /**
1368:      * Put two bytes on the stream.
1369:      *
1370:      * @param i the information to add (only lowest 16 bits are used)
1371:      */
1372:     private void putU2(int i)
1373:     {
1374:       stream.append((char) (i >> 8)).append((char) i);
1375:     }
1376: 
1377:     /**
1378:      * Put four bytes on the stream.
1379:      *
1380:      * @param i the information to add (treated as unsigned)
1381:      */
1382:     private void putU4(int i)
1383:     {
1384:       stream.append((char) (i >> 24)).append((char) (i >> 16));
1385:       stream.append((char) (i >> 8)).append((char) i);
1386:     }
1387: 
1388:     /**
1389:      * Put bytecode to load a constant integer on the stream. This only
1390:      * needs to work for values less than Short.MAX_VALUE.
1391:      *
1392:      * @param i the int to add
1393:      */
1394:     private void putConst(int i)
1395:     {
1396:       if (i >= -1 && i <= 5)
1397:         putU1(ICONST_0 + i);
1398:       else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE)
1399:         {
1400:           putU1(BIPUSH);
1401:           putU1(i);
1402:         }
1403:       else
1404:         {
1405:           putU1(SIPUSH);
1406:           putU2(i);
1407:         }
1408:     }
1409: 
1410:     /**
1411:      * Put bytecode to load a given local variable on the stream.
1412:      *
1413:      * @param i the slot to load
1414:      * @param type the base type of the load
1415:      */
1416:     private void putLoad(int i, Class type)
1417:     {
1418:       int offset = 0;
1419:       if (type == long.class)
1420:         offset = 1;
1421:       else if (type == float.class)
1422:         offset = 2;
1423:       else if (type == double.class)
1424:         offset = 3;
1425:       else if (! type.isPrimitive())
1426:         offset = 4;
1427:       if (i < 4)
1428:         putU1(ILOAD_0 + 4 * offset + i);
1429:       else
1430:         {
1431:           putU1(ILOAD + offset);
1432:           putU1(i);
1433:         }
1434:     }
1435: 
1436:     /**
1437:      * Given a primitive type, return its wrapper class name.
1438:      *
1439:      * @param clazz the primitive type (but not void.class)
1440:      * @return the internal form of the wrapper class name
1441:      */
1442:     private String wrapper(Class clazz)
1443:     {
1444:       if (clazz == boolean.class)
1445:         return "java/lang/Boolean";
1446:       if (clazz == byte.class)
1447:         return "java/lang/Byte";
1448:       if (clazz == short.class)
1449:         return "java/lang/Short";
1450:       if (clazz == char.class)
1451:         return "java/lang/Character";
1452:       if (clazz == int.class)
1453:         return "java/lang/Integer";
1454:       if (clazz == long.class)
1455:         return "java/lang/Long";
1456:       if (clazz == float.class)
1457:         return "java/lang/Float";
1458:       if (clazz == double.class)
1459:         return "java/lang/Double";
1460:       // assert false;
1461:       return null;
1462:     }
1463: 
1464:     /**
1465:      * Returns the entry of this String in the Constant pool, adding it
1466:      * if necessary.
1467:      *
1468:      * @param str the String to resolve
1469:      * @return the index of the String in the constant pool
1470:      */
1471:     private char utf8Info(String str)
1472:     {
1473:       String utf8 = toUtf8(str);
1474:       int len = utf8.length();
1475:       return poolIndex("\1" + (char) (len >> 8) + (char) (len & 0xff) + utf8);
1476:     }
1477: 
1478:     /**
1479:      * Returns the entry of the appropriate class info structure in the
1480:      * Constant pool, adding it if necessary.
1481:      *
1482:      * @param name the class name, in internal form
1483:      * @return the index of the ClassInfo in the constant pool
1484:      */
1485:     private char classInfo(String name)
1486:     {
1487:       char index = utf8Info(name);
1488:       char[] c = {7, (char) (index >> 8), (char) (index & 0xff)};
1489:       return poolIndex(new String(c));
1490:     }
1491: 
1492:     /**
1493:      * Returns the entry of the appropriate class info structure in the
1494:      * Constant pool, adding it if necessary.
1495:      *
1496:      * @param clazz the class type
1497:      * @return the index of the ClassInfo in the constant pool
1498:      */
1499:     private char classInfo(Class clazz)
1500:     {
1501:       return classInfo(TypeSignature.getEncodingOfClass(clazz.getName(),
1502:                                                         false));
1503:     }
1504: 
1505:     /**
1506:      * Returns the entry of the appropriate fieldref, methodref, or
1507:      * interfacemethodref info structure in the Constant pool, adding it
1508:      * if necessary.
1509:      *
1510:      * @param structure FIELD, METHOD, or INTERFACE
1511:      * @param clazz the class name, in internal form
1512:      * @param name the simple reference name
1513:      * @param type the type of the reference
1514:      * @return the index of the appropriate Info structure in the constant pool
1515:      */
1516:     private char refInfo(byte structure, String clazz, String name,
1517:                          String type)
1518:     {
1519:       char cindex = classInfo(clazz);
1520:       char ntindex = nameAndTypeInfo(name, type);
1521:       // relies on FIELD == 1, METHOD == 2, INTERFACE == 3
1522:       char[] c = {(char) (structure + 8),
1523:                   (char) (cindex >> 8), (char) (cindex & 0xff),
1524:                   (char) (ntindex >> 8), (char) (ntindex & 0xff)};
1525:       return poolIndex(new String(c));
1526:     }
1527: 
1528:     /**
1529:      * Returns the entry of the appropriate nameAndTyperef info structure
1530:      * in the Constant pool, adding it if necessary.
1531:      *
1532:      * @param name the simple name
1533:      * @param type the reference type
1534:      * @return the index of the NameAndTypeInfo structure in the constant pool
1535:      */
1536:     private char nameAndTypeInfo(String name, String type)
1537:     {
1538:       char nindex = utf8Info(name);
1539:       char tindex = utf8Info(type);
1540:       char[] c = {12, (char) (nindex >> 8), (char) (nindex & 0xff),
1541:                   (char) (tindex >> 8), (char) (tindex & 0xff)};
1542:       return poolIndex(new String(c));
1543:     }
1544: 
1545:     /**
1546:      * Converts a regular string to a UTF8 string, where the upper byte
1547:      * of every char is 0, and '\\u0000' is not in the string.  This is
1548:      * basically to use a String as a fancy byte[], and while it is less
1549:      * efficient in memory use, it is easier for hashing.
1550:      *
1551:      * @param str the original, in straight unicode
1552:      * @return a modified string, in UTF8 format in the low bytes
1553:      */
1554:     private String toUtf8(String str)
1555:     {
1556:       final char[] ca = str.toCharArray();
1557:       final int len = ca.length;
1558: 
1559:       // Avoid object creation, if str is already fits UTF8.
1560:       int i;
1561:       for (i = 0; i < len; i++)
1562:         if (ca[i] == 0 || ca[i] > '\u007f')
1563:           break;
1564:       if (i == len)
1565:         return str;
1566: 
1567:       final StringBuffer sb = new StringBuffer(str);
1568:       sb.setLength(i);
1569:       for ( ; i < len; i++)
1570:         {
1571:           final char c = ca[i];
1572:           if (c > 0 && c <= '\u007f')
1573:             sb.append(c);
1574:           else if (c <= '\u07ff') // includes '\0'
1575:             {
1576:               sb.append((char) (0xc0 | (c >> 6)));
1577:               sb.append((char) (0x80 | (c & 0x6f)));
1578:             }
1579:           else
1580:             {
1581:               sb.append((char) (0xe0 | (c >> 12)));
1582:               sb.append((char) (0x80 | ((c >> 6) & 0x6f)));
1583:               sb.append((char) (0x80 | (c & 0x6f)));
1584:             }
1585:         }
1586:       return sb.toString();
1587:     }
1588: 
1589:     /**
1590:      * Returns the location of a byte sequence (conveniently wrapped in
1591:      * a String with all characters between \u0001 and \u00ff inclusive)
1592:      * in the constant pool, adding it if necessary.
1593:      *
1594:      * @param sequence the byte sequence to look for
1595:      * @return the index of the sequence
1596:      * @throws IllegalArgumentException if this would make the constant
1597:      *         pool overflow
1598:      */
1599:     private char poolIndex(String sequence)
1600:     {
1601:       Integer i = (Integer) poolEntries.get(sequence);
1602:       if (i == null)
1603:         {
1604:           // pool starts at index 1
1605:           int size = poolEntries.size() + 1;
1606:           if (size >= 65535)
1607:             throw new IllegalArgumentException("exceeds VM limitations");
1608:           i = new Integer(size);
1609:           poolEntries.put(sequence, i);
1610:           pool.append(sequence);
1611:         }
1612:       return (char) i.intValue();
1613:     }
1614:   } // class ClassFactory
1615: }