return ctor.newInstance(new DebugProxy(obj));
The invocation handler's invoke method can throw Throwable. However, if invoke tHRows any
exception that the original method could not throw, the invoker will get an
UndeclaredThrowableException that returns the offending exception from its getCause method.
If you invoke getProxyClass twice with the same parameters (the same class loader and the same
interfaces in the same order) you will get back the same Class object. If the interfaces are in another order or
the class loader is different, you will get back different Class objects. The interface order matters because
two interfaces in the list can potentially have methods with the same name and signature. If this happens, the
Method object passed to invoke will have a declaring class of the first interface listed that declares that
method (defined by a depth-first search of interfaces and superinterfaces).
The declaring class for the public non-final methods of Objectequals, hashCode, and toStringis
always Object.class. The other methods of Object are not "proxied"; their methods are handled
directly by the proxy object itself, not via a call to invoke. Most importantly, this means that a lock on a
proxy object is just thata lock on the proxy. Whatever object or objects the proxy uses to do its work (for
example, in our case the underlying object whose methods are being traced) is not involved in the lock,
including any uses of wait, notifyAll, or notify.
You can ask if a Class object represents a dynamically generated proxy class using the static
Proxy.isProxyClass method.
16.13. Loading Classes
The runtime system loads classes when they are needed. Details of loading classes vary between
implementations, but most of them use a class path mechanism to search for a class referenced by your code
but not yet loaded into the runtime system. The class path is a list of places in which the system looks for class
files. This default mechanism works well in many cases, but much of the power of the Java virtual machine is
its ability to load classes from places that make sense to your application. To write an application that loads
classes in ways different from the default mechanism, you must provide a ClassLoader object that can get
the bytecodes for class implementations and load them into the runtime system.
For example, you might set up a game so that any player could write a class to play the game using whatever
strategy the player chooses. The design would look something like this: