blob: e9a1d40f95cb4ed226d88e6ffaf0d73a5d9d7c2c [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.lang.reflect;
27
28import java.lang.ref.Reference;
29import java.lang.ref.WeakReference;
30import java.util.Arrays;
31import java.util.Collections;
32import java.util.HashMap;
33import java.util.HashSet;
34import java.util.Map;
35import java.util.Set;
36import java.util.WeakHashMap;
37import sun.misc.ProxyGenerator;
38
39/**
40 * {@code Proxy} provides static methods for creating dynamic proxy
41 * classes and instances, and it is also the superclass of all
42 * dynamic proxy classes created by those methods.
43 *
44 * <p>To create a proxy for some interface {@code Foo}:
45 * <pre>
46 * InvocationHandler handler = new MyInvocationHandler(...);
47 * Class proxyClass = Proxy.getProxyClass(
48 * Foo.class.getClassLoader(), new Class[] { Foo.class });
49 * Foo f = (Foo) proxyClass.
50 * getConstructor(new Class[] { InvocationHandler.class }).
51 * newInstance(new Object[] { handler });
52 * </pre>
53 * or more simply:
54 * <pre>
55 * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
56 * new Class[] { Foo.class },
57 * handler);
58 * </pre>
59 *
60 * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
61 * class</i> below) is a class that implements a list of interfaces
62 * specified at runtime when the class is created, with behavior as
63 * described below.
64 *
65 * A <i>proxy interface</i> is such an interface that is implemented
66 * by a proxy class.
67 *
68 * A <i>proxy instance</i> is an instance of a proxy class.
69 *
70 * Each proxy instance has an associated <i>invocation handler</i>
71 * object, which implements the interface {@link InvocationHandler}.
72 * A method invocation on a proxy instance through one of its proxy
73 * interfaces will be dispatched to the {@link InvocationHandler#invoke
74 * invoke} method of the instance's invocation handler, passing the proxy
75 * instance, a {@code java.lang.reflect.Method} object identifying
76 * the method that was invoked, and an array of type {@code Object}
77 * containing the arguments. The invocation handler processes the
78 * encoded method invocation as appropriate and the result that it
79 * returns will be returned as the result of the method invocation on
80 * the proxy instance.
81 *
82 * <p>A proxy class has the following properties:
83 *
84 * <ul>
85 * <li>Proxy classes are public, final, and not abstract.
86 *
87 * <li>The unqualified name of a proxy class is unspecified. The space
88 * of class names that begin with the string {@code "$Proxy"}
89 * should be, however, reserved for proxy classes.
90 *
91 * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
92 *
93 * <li>A proxy class implements exactly the interfaces specified at its
94 * creation, in the same order.
95 *
96 * <li>If a proxy class implements a non-public interface, then it will
97 * be defined in the same package as that interface. Otherwise, the
98 * package of a proxy class is also unspecified. Note that package
99 * 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 * @see InvocationHandler
219 * @since 1.3
220 */
221public class Proxy implements java.io.Serializable {
222
223 private static final long serialVersionUID = -2222568056686623797L;
224
225 /** prefix for all proxy class names */
226 private final static String proxyClassNamePrefix = "$Proxy";
227
228 /** parameter types of a proxy class constructor */
229 private final static Class[] constructorParams =
230 { 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 =
244 Collections.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)
345 throws IllegalArgumentException
346 {
347 if (interfaces.length > 65535) {
348 throw new IllegalArgumentException("interface limit exceeded");
349 }
350
351 Class proxyClass = null;
352
353 /* collect interface names to use as key for proxy class cache */
354 String[] interfaceNames = new String[interfaces.length];
355
356 Set interfaceSet = new HashSet(); // for detecting duplicates
357
358 for (int i = 0; i < interfaces.length; i++) {
359 /*
360 * Verify that the class loader resolves the name of this
361 * interface to the same Class object.
362 */
363 String interfaceName = interfaces[i].getName();
364 Class interfaceClass = null;
365 try {
366 interfaceClass = Class.forName(interfaceName, false, loader);
367 } catch (ClassNotFoundException e) {
368 }
369 if (interfaceClass != interfaces[i]) {
370 throw new IllegalArgumentException(
371 interfaces[i] + " 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(
380 interfaceClass.getName() + " is not an interface");
381 }
382
383 /*
384 * Verify that this interface is not a duplicate.
385 */
386 if (interfaceSet.contains(interfaceClass)) {
387 throw new IllegalArgumentException(
388 "repeated interface: " + interfaceClass.getName());
389 }
390 interfaceSet.add(interfaceClass);
391
392 interfaceNames[i] = interfaceName;
393 }
394
395 /*
396 * Using string representations of the proxy interfaces as
397 * keys in the proxy class cache (instead of their Class
398 * objects) is sufficient because we require the proxy
399 * interfaces to be resolvable by name through the supplied
400 * class loader, and it has the advantage that using a string
401 * representation of a class makes for an implicit weak
402 * reference to the class.
403 */
404 Object key = Arrays.asList(interfaceNames);
405
406 /*
407 * Find or create the proxy class cache for the class loader.
408 */
409 Map cache;
410 synchronized (loaderToCache) {
411 cache = (Map) loaderToCache.get(loader);
412 if (cache == null) {
413 cache = new HashMap();
414 loaderToCache.put(loader, cache);
415 }
416 /*
417 * This mapping will remain valid for the duration of this
418 * method, without further synchronization, because the mapping
419 * will only be removed if the class loader becomes unreachable.
420 */
421 }
422
423 /*
424 * Look up the list of interfaces in the proxy class cache using
425 * the key. This lookup will result in one of three possible
426 * kinds of values:
427 * null, if there is currently no proxy class for the list of
428 * interfaces in the class loader,
429 * the pendingGenerationMarker object, if a proxy class for the
430 * list of interfaces is currently being generated,
431 * or a weak reference to a Class object, if a proxy class for
432 * the list of interfaces has already been generated.
433 */
434 synchronized (cache) {
435 /*
436 * Note that we need not worry about reaping the cache for
437 * entries with cleared weak references because if a proxy class
438 * has been garbage collected, its class loader will have been
439 * garbage collected as well, so the entire cache will be reaped
440 * from the loaderToCache map.
441 */
442 do {
443 Object value = cache.get(key);
444 if (value instanceof Reference) {
445 proxyClass = (Class) ((Reference) value).get();
446 }
447 if (proxyClass != null) {
448 // proxy class already generated: return it
449 return proxyClass;
450 } else if (value == pendingGenerationMarker) {
451 // proxy class being generated: wait for it
452 try {
453 cache.wait();
454 } catch (InterruptedException e) {
455 /*
456 * The class generation that we are waiting for should
457 * take a small, bounded time, so we can safely ignore
458 * thread interrupts here.
459 */
460 }
461 continue;
462 } else {
463 /*
464 * No proxy class for this list of interfaces has been
465 * generated or is being generated, so we will go and
466 * generate it now. Mark it as pending generation.
467 */
468 cache.put(key, pendingGenerationMarker);
469 break;
470 }
471 } while (true);
472 }
473
474 try {
475 String proxyPkg = null; // package to define proxy class in
476
477 /*
478 * Record the package of a non-public proxy interface so that the
479 * proxy class will be defined in the same package. Verify that
480 * all non-public proxy interfaces are in the same package.
481 */
482 for (int i = 0; i < interfaces.length; i++) {
483 int flags = interfaces[i].getModifiers();
484 if (!Modifier.isPublic(flags)) {
485 String name = interfaces[i].getName();
486 int n = name.lastIndexOf('.');
487 String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
488 if (proxyPkg == null) {
489 proxyPkg = pkg;
490 } else if (!pkg.equals(proxyPkg)) {
491 throw new IllegalArgumentException(
492 "non-public interfaces from different packages");
493 }
494 }
495 }
496
497 if (proxyPkg == null) { // if no non-public proxy interfaces,
498 proxyPkg = ""; // use the unnamed package
499 }
500
501 {
502 /*
503 * Choose a name for the proxy class to generate.
504 */
505 long num;
506 synchronized (nextUniqueNumberLock) {
507 num = nextUniqueNumber++;
508 }
509 String proxyName = proxyPkg + proxyClassNamePrefix + num;
510 /*
511 * Verify that the class loader hasn't already
512 * defined a class with the chosen name.
513 */
514
515 /*
516 * Generate the specified proxy class.
517 */
518 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
519 proxyName, interfaces);
520 try {
521 proxyClass = defineClass0(loader, proxyName,
522 proxyClassFile, 0, proxyClassFile.length);
523 } catch (ClassFormatError e) {
524 /*
525 * A ClassFormatError here means that (barring bugs in the
526 * proxy class generation code) there was some other
527 * invalid aspect of the arguments supplied to the proxy
528 * class creation (such as virtual machine limitations
529 * exceeded).
530 */
531 throw new IllegalArgumentException(e.toString());
532 }
533 }
534 // add to set of all generated proxy classes, for isProxyClass
535 proxyClasses.put(proxyClass, null);
536
537 } finally {
538 /*
539 * We must clean up the "pending generation" state of the proxy
540 * class cache entry somehow. If a proxy class was successfully
541 * generated, store it in the cache (with a weak reference);
542 * otherwise, remove the reserved entry. In all cases, notify
543 * all waiters on reserved entries in this cache.
544 */
545 synchronized (cache) {
546 if (proxyClass != null) {
547 cache.put(key, new WeakReference(proxyClass));
548 } else {
549 cache.remove(key);
550 }
551 cache.notifyAll();
552 }
553 }
554 return proxyClass;
555 }
556
557 /**
558 * Returns an instance of a proxy class for the specified interfaces
559 * that dispatches method invocations to the specified invocation
560 * handler. This method is equivalent to:
561 * <pre>
562 * Proxy.getProxyClass(loader, interfaces).
563 * getConstructor(new Class[] { InvocationHandler.class }).
564 * newInstance(new Object[] { handler });
565 * </pre>
566 *
567 * <p>{@code Proxy.newProxyInstance} throws
568 * {@code IllegalArgumentException} for the same reasons that
569 * {@code Proxy.getProxyClass} does.
570 *
571 * @param loader the class loader to define the proxy class
572 * @param interfaces the list of interfaces for the proxy class
573 * to implement
574 * @param h the invocation handler to dispatch method invocations to
575 * @return a proxy instance with the specified invocation handler of a
576 * proxy class that is defined by the specified class loader
577 * and that implements the specified interfaces
578 * @throws IllegalArgumentException if any of the restrictions on the
579 * parameters that may be passed to {@code getProxyClass}
580 * are violated
581 * @throws NullPointerException if the {@code interfaces} array
582 * argument or any of its elements are {@code null}, or
583 * if the invocation handler, {@code h}, is
584 * {@code null}
585 */
586 public static Object newProxyInstance(ClassLoader loader,
587 Class<?>[] interfaces,
588 InvocationHandler h)
589 throws IllegalArgumentException
590 {
591 if (h == null) {
592 throw new NullPointerException();
593 }
594
595 /*
596 * Look up or generate the designated proxy class.
597 */
598 Class cl = getProxyClass(loader, interfaces);
599
600 /*
601 * Invoke its constructor with the designated invocation handler.
602 */
603 try {
604 Constructor cons = cl.getConstructor(constructorParams);
605 return (Object) cons.newInstance(new Object[] { h });
606 } catch (NoSuchMethodException e) {
607 throw new InternalError(e.toString());
608 } catch (IllegalAccessException e) {
609 throw new InternalError(e.toString());
610 } catch (InstantiationException e) {
611 throw new InternalError(e.toString());
612 } catch (InvocationTargetException e) {
613 throw new InternalError(e.toString());
614 }
615 }
616
617 /**
618 * Returns true if and only if the specified class was dynamically
619 * generated to be a proxy class using the {@code getProxyClass}
620 * method or the {@code newProxyInstance} method.
621 *
622 * <p>The reliability of this method is important for the ability
623 * to use it to make security decisions, so its implementation should
624 * not just test if the class in question extends {@code Proxy}.
625 *
626 * @param cl the class to test
627 * @return {@code true} if the class is a proxy class and
628 * {@code false} otherwise
629 * @throws NullPointerException if {@code cl} is {@code null}
630 */
631 public static boolean isProxyClass(Class<?> cl) {
632 if (cl == null) {
633 throw new NullPointerException();
634 }
635
636 return proxyClasses.containsKey(cl);
637 }
638
639 /**
640 * Returns the invocation handler for the specified proxy instance.
641 *
642 * @param proxy the proxy instance to return the invocation handler for
643 * @return the invocation handler for the proxy instance
644 * @throws IllegalArgumentException if the argument is not a
645 * proxy instance
646 */
647 public static InvocationHandler getInvocationHandler(Object proxy)
648 throws IllegalArgumentException
649 {
650 /*
651 * Verify that the object is actually a proxy instance.
652 */
653 if (!isProxyClass(proxy.getClass())) {
654 throw new IllegalArgumentException("not a proxy instance");
655 }
656
657 Proxy p = (Proxy) proxy;
658 return p.h;
659 }
660
661 private static native Class defineClass0(ClassLoader loader, String name,
662 byte[] b, int off, int len);
663}