001 /*
002 * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.lang.reflect;
027
028 import java.lang.ref.Reference;
029 import java.lang.ref.WeakReference;
030 import java.util.Arrays;
031 import java.util.Collections;
032 import java.util.HashMap;
033 import java.util.HashSet;
034 import java.util.Map;
035 import java.util.Set;
036 import java.util.WeakHashMap;
037 import sun.misc.ProxyGenerator;
038
039 /**
040 * {@code Proxy} provides static methods for creating dynamic proxy
041 * classes and instances, and it is also the superclass of all
042 * dynamic proxy classes created by those methods.
043 *
044 * <p>To create a proxy for some interface {@code Foo}:
045 * <pre>
046 * InvocationHandler handler = new MyInvocationHandler(...);
047 * Class proxyClass = Proxy.getProxyClass(
048 * Foo.class.getClassLoader(), new Class[] { Foo.class });
049 * Foo f = (Foo) proxyClass.
050 * getConstructor(new Class[] { InvocationHandler.class }).
051 * newInstance(new Object[] { handler });
052 * </pre>
053 * or more simply:
054 * <pre>
055 * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
056 * new Class[] { Foo.class },
057 * handler);
058 * </pre>
059 *
060 * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
061 * class</i> below) is a class that implements a list of interfaces
062 * specified at runtime when the class is created, with behavior as
063 * described below.
064 *
065 * A <i>proxy interface</i> is such an interface that is implemented
066 * by a proxy class.
067 *
068 * A <i>proxy instance</i> is an instance of a proxy class.
069 *
070 * Each proxy instance has an associated <i>invocation handler</i>
071 * object, which implements the interface {@link InvocationHandler}.
072 * A method invocation on a proxy instance through one of its proxy
073 * interfaces will be dispatched to the {@link InvocationHandler#invoke
074 * invoke} method of the instance's invocation handler, passing the proxy
075 * instance, a {@code java.lang.reflect.Method} object identifying
076 * the method that was invoked, and an array of type {@code Object}
077 * containing the arguments. The invocation handler processes the
078 * encoded method invocation as appropriate and the result that it
079 * returns will be returned as the result of the method invocation on
080 * the proxy instance.
081 *
082 * <p>A proxy class has the following properties:
083 *
084 * <ul>
085 * <li>Proxy classes are public, final, and not abstract.
086 *
087 * <li>The unqualified name of a proxy class is unspecified. The space
088 * of class names that begin with the string {@code "$Proxy"}
089 * should be, however, reserved for proxy classes.
090 *
091 * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
092 *
093 * <li>A proxy class implements exactly the interfaces specified at its
094 * creation, in the same order.
095 *
096 * <li>If a proxy class implements a non-public interface, then it will
097 * be defined in the same package as that interface. Otherwise, the
098 * package of a proxy class is also unspecified. Note that package
099 * sealing will not prevent a proxy class from being successfully defined
100 * in a particular package at runtime, and neither will classes already
101 * defined by the same class loader and the same package with particular
102 * signers.
103 *
104 * <li>Since a proxy class implements all of the interfaces specified at
105 * its creation, invoking {@code getInterfaces} on its
106 * {@code Class} object will return an array containing the same
107 * list of interfaces (in the order specified at its creation), invoking
108 * {@code getMethods} on its {@code Class} object will return
109 * an array of {@code Method} objects that include all of the
110 * methods in those interfaces, and invoking {@code getMethod} will
111 * find methods in the proxy interfaces as would be expected.
112 *
113 * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
114 * return true if it is passed a proxy class-- a class returned by
115 * {@code Proxy.getProxyClass} or the class of an object returned by
116 * {@code Proxy.newProxyInstance}-- and false otherwise.
117 *
118 * <li>The {@code java.security.ProtectionDomain} of a proxy class
119 * is the same as that of system classes loaded by the bootstrap class
120 * loader, such as {@code java.lang.Object}, because the code for a
121 * proxy class is generated by trusted system code. This protection
122 * domain will typically be granted
123 * {@code java.security.AllPermission}.
124 *
125 * <li>Each proxy class has one public constructor that takes one argument,
126 * an implementation of the interface {@link InvocationHandler}, to set
127 * the invocation handler for a proxy instance. Rather than having to use
128 * the reflection API to access the public constructor, a proxy instance
129 * can be also be created by calling the {@link Proxy#newProxyInstance
130 * Proxy.newProxyInstance} method, which combines the actions of calling
131 * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
132 * constructor with an invocation handler.
133 * </ul>
134 *
135 * <p>A proxy instance has the following properties:
136 *
137 * <ul>
138 * <li>Given a proxy instance {@code proxy} and one of the
139 * interfaces implemented by its proxy class {@code Foo}, the
140 * following expression will return true:
141 * <pre>
142 * {@code proxy instanceof Foo}
143 * </pre>
144 * and the following cast operation will succeed (rather than throwing
145 * a {@code ClassCastException}):
146 * <pre>
147 * {@code (Foo) proxy}
148 * </pre>
149 *
150 * <li>Each proxy instance has an associated invocation handler, the one
151 * that was passed to its constructor. The static
152 * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
153 * will return the invocation handler associated with the proxy instance
154 * passed as its argument.
155 *
156 * <li>An interface method invocation on a proxy instance will be
157 * encoded and dispatched to the invocation handler's {@link
158 * InvocationHandler#invoke invoke} method as described in the
159 * documentation for that method.
160 *
161 * <li>An invocation of the {@code hashCode},
162 * {@code equals}, or {@code toString} methods declared in
163 * {@code java.lang.Object} on a proxy instance will be encoded and
164 * dispatched to the invocation handler's {@code invoke} method in
165 * the same manner as interface method invocations are encoded and
166 * dispatched, as described above. The declaring class of the
167 * {@code Method} object passed to {@code invoke} will be
168 * {@code java.lang.Object}. Other public methods of a proxy
169 * instance inherited from {@code java.lang.Object} are not
170 * overridden by a proxy class, so invocations of those methods behave
171 * like they do for instances of {@code java.lang.Object}.
172 * </ul>
173 *
174 * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
175 *
176 * <p>When two or more interfaces of a proxy class contain a method with
177 * the same name and parameter signature, the order of the proxy class's
178 * interfaces becomes significant. When such a <i>duplicate method</i>
179 * is invoked on a proxy instance, the {@code Method} object passed
180 * to the invocation handler will not necessarily be the one whose
181 * declaring class is assignable from the reference type of the interface
182 * that the proxy's method was invoked through. This limitation exists
183 * because the corresponding method implementation in the generated proxy
184 * class cannot determine which interface it was invoked through.
185 * Therefore, when a duplicate method is invoked on a proxy instance,
186 * the {@code Method} object for the method in the foremost interface
187 * that contains the method (either directly or inherited through a
188 * superinterface) in the proxy class's list of interfaces is passed to
189 * the invocation handler's {@code invoke} method, regardless of the
190 * reference type through which the method invocation occurred.
191 *
192 * <p>If a proxy interface contains a method with the same name and
193 * parameter signature as the {@code hashCode}, {@code equals},
194 * or {@code toString} methods of {@code java.lang.Object},
195 * when such a method is invoked on a proxy instance, the
196 * {@code Method} object passed to the invocation handler will have
197 * {@code java.lang.Object} as its declaring class. In other words,
198 * the public, non-final methods of {@code java.lang.Object}
199 * logically precede all of the proxy interfaces for the determination of
200 * which {@code Method} object to pass to the invocation handler.
201 *
202 * <p>Note also that when a duplicate method is dispatched to an
203 * invocation handler, the {@code invoke} method may only throw
204 * checked exception types that are assignable to one of the exception
205 * types in the {@code throws} clause of the method in <i>all</i> of
206 * the proxy interfaces that it can be invoked through. If the
207 * {@code invoke} method throws a checked exception that is not
208 * assignable to any of the exception types declared by the method in one
209 * of the proxy interfaces that it can be invoked through, then an
210 * unchecked {@code UndeclaredThrowableException} will be thrown by
211 * the invocation on the proxy instance. This restriction means that not
212 * all of the exception types returned by invoking
213 * {@code getExceptionTypes} on the {@code Method} object
214 * passed to the {@code invoke} method can necessarily be thrown
215 * successfully by the {@code invoke} method.
216 *
217 * @author Peter Jones
218 * @version 1.30, 07/06/22
219 * @see InvocationHandler
220 * @since 1.3
221 */
222 public class Proxy implements java.io.Serializable {
223
224 private static final long serialVersionUID = -2222568056686623797L;
225
226 /** prefix for all proxy class names */
227 private final static String proxyClassNamePrefix = "$Proxy";
228
229 /** parameter types of a proxy class constructor */
230 private final static Class[] constructorParams = { InvocationHandler.class };
231
232 /** maps a class loader to the proxy class cache for that loader */
233 private static Map loaderToCache = new WeakHashMap();
234
235 /** marks that a particular proxy class is currently being generated */
236 private static Object pendingGenerationMarker = new Object();
237
238 /** next number to use for generation of unique proxy class names */
239 private static long nextUniqueNumber = 0;
240 private static Object nextUniqueNumberLock = new Object();
241
242 /** set of all generated proxy classes, for isProxyClass implementation */
243 private static Map proxyClasses = Collections
244 .synchronizedMap(new WeakHashMap());
245
246 /**
247 * the invocation handler for this proxy instance.
248 * @serial
249 */
250 protected InvocationHandler h;
251
252 /**
253 * Prohibits instantiation.
254 */
255 private Proxy() {
256 }
257
258 /**
259 * Constructs a new {@code Proxy} instance from a subclass
260 * (typically, a dynamic proxy class) with the specified value
261 * for its invocation handler.
262 *
263 * @param h the invocation handler for this proxy instance
264 */
265 protected Proxy(InvocationHandler h) {
266 this .h = h;
267 }
268
269 /**
270 * Returns the {@code java.lang.Class} object for a proxy class
271 * given a class loader and an array of interfaces. The proxy class
272 * will be defined by the specified class loader and will implement
273 * all of the supplied interfaces. If a proxy class for the same
274 * permutation of interfaces has already been defined by the class
275 * loader, then the existing proxy class will be returned; otherwise,
276 * a proxy class for those interfaces will be generated dynamically
277 * and defined by the class loader.
278 *
279 * <p>There are several restrictions on the parameters that may be
280 * passed to {@code Proxy.getProxyClass}:
281 *
282 * <ul>
283 * <li>All of the {@code Class} objects in the
284 * {@code interfaces} array must represent interfaces, not
285 * classes or primitive types.
286 *
287 * <li>No two elements in the {@code interfaces} array may
288 * refer to identical {@code Class} objects.
289 *
290 * <li>All of the interface types must be visible by name through the
291 * specified class loader. In other words, for class loader
292 * {@code cl} and every interface {@code i}, the following
293 * expression must be true:
294 * <pre>
295 * Class.forName(i.getName(), false, cl) == i
296 * </pre>
297 *
298 * <li>All non-public interfaces must be in the same package;
299 * otherwise, it would not be possible for the proxy class to
300 * implement all of the interfaces, regardless of what package it is
301 * defined in.
302 *
303 * <li>For any set of member methods of the specified interfaces
304 * that have the same signature:
305 * <ul>
306 * <li>If the return type of any of the methods is a primitive
307 * type or void, then all of the methods must have that same
308 * return type.
309 * <li>Otherwise, one of the methods must have a return type that
310 * is assignable to all of the return types of the rest of the
311 * methods.
312 * </ul>
313 *
314 * <li>The resulting proxy class must not exceed any limits imposed
315 * on classes by the virtual machine. For example, the VM may limit
316 * the number of interfaces that a class may implement to 65535; in
317 * that case, the size of the {@code interfaces} array must not
318 * exceed 65535.
319 * </ul>
320 *
321 * <p>If any of these restrictions are violated,
322 * {@code Proxy.getProxyClass} will throw an
323 * {@code IllegalArgumentException}. If the {@code interfaces}
324 * array argument or any of its elements are {@code null}, a
325 * {@code NullPointerException} will be thrown.
326 *
327 * <p>Note that the order of the specified proxy interfaces is
328 * significant: two requests for a proxy class with the same combination
329 * of interfaces but in a different order will result in two distinct
330 * proxy classes.
331 *
332 * @param loader the class loader to define the proxy class
333 * @param interfaces the list of interfaces for the proxy class
334 * to implement
335 * @return a proxy class that is defined in the specified class loader
336 * and that implements the specified interfaces
337 * @throws IllegalArgumentException if any of the restrictions on the
338 * parameters that may be passed to {@code getProxyClass}
339 * are violated
340 * @throws NullPointerException if the {@code interfaces} array
341 * argument or any of its elements are {@code null}
342 */
343 public static Class<?> getProxyClass(ClassLoader loader,
344 Class<?>... interfaces) throws IllegalArgumentException {
345 if (interfaces.length > 65535) {
346 throw new IllegalArgumentException(
347 "interface limit exceeded");
348 }
349
350 Class proxyClass = null;
351
352 /* collect interface names to use as key for proxy class cache */
353 String[] interfaceNames = new String[interfaces.length];
354
355 Set interfaceSet = new HashSet(); // for detecting duplicates
356
357 for (int i = 0; i < interfaces.length; i++) {
358 /*
359 * Verify that the class loader resolves the name of this
360 * interface to the same Class object.
361 */
362 String interfaceName = interfaces[i].getName();
363 Class interfaceClass = null;
364 try {
365 interfaceClass = Class.forName(interfaceName, false,
366 loader);
367 } catch (ClassNotFoundException e) {
368 }
369 if (interfaceClass != interfaces[i]) {
370 throw new IllegalArgumentException(interfaces[i]
371 + " is not visible from class loader");
372 }
373
374 /*
375 * Verify that the Class object actually represents an
376 * interface.
377 */
378 if (!interfaceClass.isInterface()) {
379 throw new IllegalArgumentException(interfaceClass
380 .getName()
381 + " is not an interface");
382 }
383
384 /*
385 * Verify that this interface is not a duplicate.
386 */
387 if (interfaceSet.contains(interfaceClass)) {
388 throw new IllegalArgumentException(
389 "repeated interface: "
390 + interfaceClass.getName());
391 }
392 interfaceSet.add(interfaceClass);
393
394 interfaceNames[i] = interfaceName;
395 }
396
397 /*
398 * Using string representations of the proxy interfaces as
399 * keys in the proxy class cache (instead of their Class
400 * objects) is sufficient because we require the proxy
401 * interfaces to be resolvable by name through the supplied
402 * class loader, and it has the advantage that using a string
403 * representation of a class makes for an implicit weak
404 * reference to the class.
405 */
406 Object key = Arrays.asList(interfaceNames);
407
408 /*
409 * Find or create the proxy class cache for the class loader.
410 */
411 Map cache;
412 synchronized (loaderToCache) {
413 cache = (Map) loaderToCache.get(loader);
414 if (cache == null) {
415 cache = new HashMap();
416 loaderToCache.put(loader, cache);
417 }
418 /*
419 * This mapping will remain valid for the duration of this
420 * method, without further synchronization, because the mapping
421 * will only be removed if the class loader becomes unreachable.
422 */
423 }
424
425 /*
426 * Look up the list of interfaces in the proxy class cache using
427 * the key. This lookup will result in one of three possible
428 * kinds of values:
429 * null, if there is currently no proxy class for the list of
430 * interfaces in the class loader,
431 * the pendingGenerationMarker object, if a proxy class for the
432 * list of interfaces is currently being generated,
433 * or a weak reference to a Class object, if a proxy class for
434 * the list of interfaces has already been generated.
435 */
436 synchronized (cache) {
437 /*
438 * Note that we need not worry about reaping the cache for
439 * entries with cleared weak references because if a proxy class
440 * has been garbage collected, its class loader will have been
441 * garbage collected as well, so the entire cache will be reaped
442 * from the loaderToCache map.
443 */
444 do {
445 Object value = cache.get(key);
446 if (value instanceof Reference) {
447 proxyClass = (Class) ((Reference) value).get();
448 }
449 if (proxyClass != null) {
450 // proxy class already generated: return it
451 return proxyClass;
452 } else if (value == pendingGenerationMarker) {
453 // proxy class being generated: wait for it
454 try {
455 cache.wait();
456 } catch (InterruptedException e) {
457 /*
458 * The class generation that we are waiting for should
459 * take a small, bounded time, so we can safely ignore
460 * thread interrupts here.
461 */
462 }
463 continue;
464 } else {
465 /*
466 * No proxy class for this list of interfaces has been
467 * generated or is being generated, so we will go and
468 * generate it now. Mark it as pending generation.
469 */
470 cache.put(key, pendingGenerationMarker);
471 break;
472 }
473 } while (true);
474 }
475
476 try {
477 String proxyPkg = null; // package to define proxy class in
478
479 /*
480 * Record the package of a non-public proxy interface so that the
481 * proxy class will be defined in the same package. Verify that
482 * all non-public proxy interfaces are in the same package.
483 */
484 for (int i = 0; i < interfaces.length; i++) {
485 int flags = interfaces[i].getModifiers();
486 if (!Modifier.isPublic(flags)) {
487 String name = interfaces[i].getName();
488 int n = name.lastIndexOf('.');
489 String pkg = ((n == -1) ? "" : name.substring(0,
490 n + 1));
491 if (proxyPkg == null) {
492 proxyPkg = pkg;
493 } else if (!pkg.equals(proxyPkg)) {
494 throw new IllegalArgumentException(
495 "non-public interfaces from different packages");
496 }
497 }
498 }
499
500 if (proxyPkg == null) { // if no non-public proxy interfaces,
501 proxyPkg = ""; // use the unnamed package
502 }
503
504 {
505 /*
506 * Choose a name for the proxy class to generate.
507 */
508 long num;
509 synchronized (nextUniqueNumberLock) {
510 num = nextUniqueNumber++;
511 }
512 String proxyName = proxyPkg + proxyClassNamePrefix
513 + num;
514 /*
515 * Verify that the class loader hasn't already
516 * defined a class with the chosen name.
517 */
518
519 /*
520 * Generate the specified proxy class.
521 */
522 byte[] proxyClassFile = ProxyGenerator
523 .generateProxyClass(proxyName, interfaces);
524 try {
525 proxyClass = defineClass0(loader, proxyName,
526 proxyClassFile, 0, proxyClassFile.length);
527 } catch (ClassFormatError e) {
528 /*
529 * A ClassFormatError here means that (barring bugs in the
530 * proxy class generation code) there was some other
531 * invalid aspect of the arguments supplied to the proxy
532 * class creation (such as virtual machine limitations
533 * exceeded).
534 */
535 throw new IllegalArgumentException(e.toString());
536 }
537 }
538 // add to set of all generated proxy classes, for isProxyClass
539 proxyClasses.put(proxyClass, null);
540
541 } finally {
542 /*
543 * We must clean up the "pending generation" state of the proxy
544 * class cache entry somehow. If a proxy class was successfully
545 * generated, store it in the cache (with a weak reference);
546 * otherwise, remove the reserved entry. In all cases, notify
547 * all waiters on reserved entries in this cache.
548 */
549 synchronized (cache) {
550 if (proxyClass != null) {
551 cache.put(key, new WeakReference(proxyClass));
552 } else {
553 cache.remove(key);
554 }
555 cache.notifyAll();
556 }
557 }
558 return proxyClass;
559 }
560
561 /**
562 * Returns an instance of a proxy class for the specified interfaces
563 * that dispatches method invocations to the specified invocation
564 * handler. This method is equivalent to:
565 * <pre>
566 * Proxy.getProxyClass(loader, interfaces).
567 * getConstructor(new Class[] { InvocationHandler.class }).
568 * newInstance(new Object[] { handler });
569 * </pre>
570 *
571 * <p>{@code Proxy.newProxyInstance} throws
572 * {@code IllegalArgumentException} for the same reasons that
573 * {@code Proxy.getProxyClass} does.
574 *
575 * @param loader the class loader to define the proxy class
576 * @param interfaces the list of interfaces for the proxy class
577 * to implement
578 * @param h the invocation handler to dispatch method invocations to
579 * @return a proxy instance with the specified invocation handler of a
580 * proxy class that is defined by the specified class loader
581 * and that implements the specified interfaces
582 * @throws IllegalArgumentException if any of the restrictions on the
583 * parameters that may be passed to {@code getProxyClass}
584 * are violated
585 * @throws NullPointerException if the {@code interfaces} array
586 * argument or any of its elements are {@code null}, or
587 * if the invocation handler, {@code h}, is
588 * {@code null}
589 */
590 public static Object newProxyInstance(ClassLoader loader,
591 Class<?>[] interfaces, InvocationHandler h)
592 throws IllegalArgumentException {
593 if (h == null) {
594 throw new NullPointerException();
595 }
596
597 /*
598 * Look up or generate the designated proxy class.
599 */
600 Class cl = getProxyClass(loader, interfaces);
601
602 /*
603 * Invoke its constructor with the designated invocation handler.
604 */
605 try {
606 Constructor cons = cl.getConstructor(constructorParams);
607 return (Object) cons.newInstance(new Object[] { h });
608 } catch (NoSuchMethodException e) {
609 throw new InternalError(e.toString());
610 } catch (IllegalAccessException e) {
611 throw new InternalError(e.toString());
612 } catch (InstantiationException e) {
613 throw new InternalError(e.toString());
614 } catch (InvocationTargetException e) {
615 throw new InternalError(e.toString());
616 }
617 }
618
619 /**
620 * Returns true if and only if the specified class was dynamically
621 * generated to be a proxy class using the {@code getProxyClass}
622 * method or the {@code newProxyInstance} method.
623 *
624 * <p>The reliability of this method is important for the ability
625 * to use it to make security decisions, so its implementation should
626 * not just test if the class in question extends {@code Proxy}.
627 *
628 * @param cl the class to test
629 * @return {@code true} if the class is a proxy class and
630 * {@code false} otherwise
631 * @throws NullPointerException if {@code cl} is {@code null}
632 */
633 public static boolean isProxyClass(Class<?> cl) {
634 if (cl == null) {
635 throw new NullPointerException();
636 }
637
638 return proxyClasses.containsKey(cl);
639 }
640
641 /**
642 * Returns the invocation handler for the specified proxy instance.
643 *
644 * @param proxy the proxy instance to return the invocation handler for
645 * @return the invocation handler for the proxy instance
646 * @throws IllegalArgumentException if the argument is not a
647 * proxy instance
648 */
649 public static InvocationHandler getInvocationHandler(Object proxy)
650 throws IllegalArgumentException {
651 /*
652 * Verify that the object is actually a proxy instance.
653 */
654 if (!isProxyClass(proxy.getClass())) {
655 throw new IllegalArgumentException("not a proxy instance");
656 }
657
658 Proxy p = (Proxy) proxy;
659 return p.h;
660 }
661
662 private static native Class defineClass0(ClassLoader loader,
663 String name, byte[] b, int off, int len);
664 }
|