|
From: <ls...@us...> - 2007-01-04 20:29:46
|
Revision: 2987
http://jnode.svn.sourceforge.net/jnode/?rev=2987&view=rev
Author: lsantha
Date: 2007-01-04 12:29:43 -0800 (Thu, 04 Jan 2007)
Log Message:
-----------
Classpath updates.
Modified Paths:
--------------
trunk/core/src/classpath/java/java/lang/reflect/Proxy.java
Modified: trunk/core/src/classpath/java/java/lang/reflect/Proxy.java
===================================================================
--- trunk/core/src/classpath/java/java/lang/reflect/Proxy.java 2007-01-04 20:24:57 UTC (rev 2986)
+++ trunk/core/src/classpath/java/java/lang/reflect/Proxy.java 2007-01-04 20:29:43 UTC (rev 2987)
@@ -1,48 +1,49 @@
/* Proxy.java -- build a proxy class that implements reflected interfaces
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
- This file is part of GNU Classpath.
+This file is part of GNU Classpath.
- GNU Classpath is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
- GNU Classpath is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU Classpath; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA.
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
- Linking this library statically or dynamically with other modules is
- making a combined work based on this library. Thus, the terms and
- conditions of the GNU General Public License cover the whole
- combination.
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
- As a special exception, the copyright holders of this library give you
- permission to link this library with independent modules to produce an
- executable, regardless of the license terms of these independent
- modules, and to copy and distribute the resulting executable under
- terms of your choice, provided that you also meet, for each linked
- independent module, the terms and conditions of the license of that
- module. An independent module is a module which is not derived from
- or based on this library. If you modify this library, you may extend
- this exception to your version of the library, but you are not
- obligated to do so. If you do not wish to do so, delete this
- exception statement from your version. */
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
package java.lang.reflect;
import gnu.java.lang.reflect.TypeSignature;
import java.io.Serializable;
+import java.security.ProtectionDomain;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -51,11 +52,12 @@
import java.util.Set;
/**
- * This class allows you to dynamically create an instance of any (or even
- * multiple) interfaces by reflection, and decide at runtime how that instance
- * will behave by giving it an appropriate {@link InvocationHandler}. Proxy
- * classes serialize specially, so that the proxy object can be reused between
- * VMs, without requiring a persistent copy of the generated class code.
+ * This class allows you to dynamically create an instance of any (or
+ * even multiple) interfaces by reflection, and decide at runtime
+ * how that instance will behave by giving it an appropriate
+ * {@link InvocationHandler}. Proxy classes serialize specially, so
+ * that the proxy object can be reused between VMs, without requiring
+ * a persistent copy of the generated class code.
*
* <h3>Creation</h3>
* To create a proxy for some interface Foo:
@@ -68,84 +70,87 @@
* .getConstructor(new Class[] { InvocationHandler.class })
* .newInstance(new Object[] { handler });
* </pre>
- *
* or more simply:
- *
* <pre>
* Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- * new Class[] { Foo.class }, handler);
+ * new Class[] { Foo.class },
+ * handler);
* </pre>
*
* <h3>Dynamic Proxy Classes</h3>
* A dynamic proxy class is created at runtime, and has the following
* properties:
* <ul>
- * <li>The class is <code>public</code> and <code>final</code>, and is
- * neither <code>abstract</code> nor an inner class.</li>
- * <li>The class has no canonical name (there is no formula you can use to
- * determine or generate its name), but begins with the sequence "$Proxy". Abuse
- * this knowledge at your own peril. (For now, '$' in user identifiers is legal,
- * but it may not be that way forever. You weren't using '$' in your
+ * <li>The class is <code>public</code> and <code>final</code>,
+ * and is neither <code>abstract</code> nor an inner class.</li>
+ * <li>The class has no canonical name (there is no formula you can use
+ * to determine or generate its name), but begins with the
+ * sequence "$Proxy". Abuse this knowledge at your own peril.
+ * (For now, '$' in user identifiers is legal, but it may not
+ * be that way forever. You weren't using '$' in your
* identifiers, were you?)</li>
- * <li>The class extends Proxy, and explicitly implements all the interfaces
- * specified at creation, in order (this is important for determining how method
- * invocation is resolved). Note that a proxy class implements
- * {@link Serializable}, at least implicitly, since Proxy does, but true serial
- * behavior depends on using a serializable invocation handler as well.</li>
- * <li>If at least one interface is non-public, the proxy class will be in the
- * same package. Otherwise, the package is unspecified. This will work even if
- * the package is sealed from user-generated classes, because Proxy classes are
- * generated by a trusted source. Meanwhile, the proxy class belongs to the
- * classloader you designated.</li>
+ * <li>The class extends Proxy, and explicitly implements all the
+ * interfaces specified at creation, in order (this is important
+ * for determining how method invocation is resolved). Note that
+ * a proxy class implements {@link Serializable}, at least
+ * implicitly, since Proxy does, but true serial behavior
+ * depends on using a serializable invocation handler as well.</li>
+ * <li>If at least one interface is non-public, the proxy class
+ * will be in the same package. Otherwise, the package is
+ * unspecified. This will work even if the package is sealed
+ * from user-generated classes, because Proxy classes are
+ * generated by a trusted source. Meanwhile, the proxy class
+ * belongs to the classloader you designated.</li>
* <li>Reflection works as expected: {@link Class#getInterfaces()} and
* {@link Class#getMethods()} work as they do on normal classes.</li>
- * <li>The method {@link #isProxyClass(Class)} will distinguish between true
- * proxy classes and user extensions of this class. It only returns true for
- * classes created by {@link #getProxyClass}.</li>
+ * <li>The method {@link #isProxyClass(Class)} will distinguish between
+ * true proxy classes and user extensions of this class. It only
+ * returns true for classes created by {@link #getProxyClass}.</li>
* <li>The {@link ProtectionDomain} of a proxy class is the same as for
- * bootstrap classes, such as Object or Proxy, since it is created by a trusted
- * source. This protection domain will typically be granted
- * {@link java.security.AllPermission}. But this is not a security risk, since
- * there are adequate permissions on reflection, which is the only way to create
- * an instance of the proxy class.</li>
- * <li>The proxy class contains a single constructor, which takes as its only
- * argument an {@link InvocationHandler}. The method
- * {@link #newProxyInstance(ClassLoader, Class[], InvocationHandler)} is
- * shorthand to do the necessary reflection.</li>
+ * bootstrap classes, such as Object or Proxy, since it is created by
+ * a trusted source. This protection domain will typically be granted
+ * {@link java.security.AllPermission}. But this is not a security
+ * risk, since there are adequate permissions on reflection, which is
+ * the only way to create an instance of the proxy class.</li>
+ * <li>The proxy class contains a single constructor, which takes as
+ * its only argument an {@link InvocationHandler}. The method
+ * {@link #newProxyInstance(ClassLoader, Class[], InvocationHandler)}
+ * is shorthand to do the necessary reflection.</li>
* </ul>
*
* <h3>Proxy Instances</h3>
- * A proxy instance is an instance of a proxy class. It has the following
- * properties, many of which follow from the properties of a proxy class listed
- * above:
+ * A proxy instance is an instance of a proxy class. It has the
+ * following properties, many of which follow from the properties of a
+ * proxy class listed above:
* <ul>
* <li>For a proxy class with Foo listed as one of its interfaces, the
- * expression <code>proxy instanceof Foo</code> will return true, and the
- * expression <code>(Foo) proxy</code> will succeed without a
- * {@link ClassCastException}.</li>
- * <li>Each proxy instance has an invocation handler, which can be accessed by
- * {@link #getInvocationHandler(Object)}. Any call to an interface method,
- * including {@link Object#hashCode()}, {@link Object#equals(Object)}, or
- * {@link Object#toString()}, but excluding the public final methods of Object,
- * will be encoded and passed to the {@link InvocationHandler#invoke} method of
- * this handler.</li>
+ * expression <code>proxy instanceof Foo</code> will return true,
+ * and the expression <code>(Foo) proxy</code> will succeed without
+ * a {@link ClassCastException}.</li>
+ * <li>Each proxy instance has an invocation handler, which can be
+ * accessed by {@link #getInvocationHandler(Object)}. Any call
+ * to an interface method, including {@link Object#hashCode()},
+ * {@link Object#equals(Object)}, or {@link Object#toString()},
+ * but excluding the public final methods of Object, will be
+ * encoded and passed to the {@link InvocationHandler#invoke}
+ * method of this handler.</li>
* </ul>
*
* <h3>Inheritance Issues</h3>
- * A proxy class may inherit a method from more than one interface. The order in
- * which interfaces are listed matters, because it determines which reflected
- * {@link Method} object will be passed to the invocation handler. This means
- * that the dynamically generated class cannot determine through which interface
- * a method is being invoked.
- * <p>
- *
- * In short, if a method is declared in Object (namely, hashCode, equals, or
- * toString), then Object will be used; otherwise, the leftmost interface that
- * inherits or declares a method will be used, even if it has a more permissive
- * throws clause than what the proxy class is allowed. Thus, in the invocation
- * handler, it is not always safe to assume that every class listed in the
- * throws clause of the passed Method object can safely be thrown; fortunately,
- * the Proxy instance is robust enough to wrap all illegal checked exceptions in
+ * A proxy class may inherit a method from more than one interface.
+ * The order in which interfaces are listed matters, because it determines
+ * which reflected {@link Method} object will be passed to the invocation
+ * handler. This means that the dynamically generated class cannot
+ * determine through which interface a method is being invoked.<p>
+ *
+ * In short, if a method is declared in Object (namely, hashCode,
+ * equals, or toString), then Object will be used; otherwise, the
+ * leftmost interface that inherits or declares a method will be used,
+ * even if it has a more permissive throws clause than what the proxy
+ * class is allowed. Thus, in the invocation handler, it is not always
+ * safe to assume that every class listed in the throws clause of the
+ * passed Method object can safely be thrown; fortunately, the Proxy
+ * instance is robust enough to wrap all illegal checked exceptions in
* {@link UndeclaredThrowableException}.
*
* @see InvocationHandler
@@ -155,7 +160,8 @@
* @since 1.3
* @status updated to 1.4, except for the use of ProtectionDomain
*/
-public class Proxy implements Serializable {
+public class Proxy implements Serializable
+{
/**
* Compatible with JDK 1.3+.
*/
@@ -171,164 +177,166 @@
private static final Map proxyClasses = new HashMap();
/**
- * The invocation handler for this proxy instance. For Proxy, this field is
- * unused, but it appears here in order to be serialized in all proxy
- * classes.
+ * The invocation handler for this proxy instance. For Proxy, this
+ * field is unused, but it appears here in order to be serialized in all
+ * proxy classes.
*
* <em>NOTE</em>: This implementation is more secure for proxy classes
- * than what Sun specifies. Sun does not require h to be immutable, but this
- * means you could change h after the fact by reflection. However, by making
- * h immutable, we may break non-proxy classes which extend Proxy.
- *
+ * than what Sun specifies. Sun does not require h to be immutable, but
+ * this means you could change h after the fact by reflection. However,
+ * by making h immutable, we may break non-proxy classes which extend
+ * Proxy.
* @serial invocation handler associated with this proxy instance
*/
protected InvocationHandler h;
/**
- * Constructs a new Proxy from a subclass (usually a proxy class), with the
- * specified invocation handler.
+ * Constructs a new Proxy from a subclass (usually a proxy class),
+ * with the specified invocation handler.
*
- * <em>NOTE</em>: This throws a NullPointerException if you attempt to
- * create a proxy instance with a null handler using reflection. This
- * behavior is not yet specified by Sun; see Sun Bug 4487672.
- *
- * @param handler
- * the invocation handler, may be null if the subclass is not a
- * proxy class
- * @throws NullPointerException
- * if handler is null and this is a proxy instance
+ * <em>NOTE</em>: This throws a NullPointerException if you attempt
+ * to create a proxy instance with a null handler using reflection.
+ * This behavior is not yet specified by Sun; see Sun Bug 4487672.
+ *
+ * @param handler the invocation handler, may be null if the subclass
+ * is not a proxy class
+ * @throws NullPointerException if handler is null and this is a proxy
+ * instance
*/
- protected Proxy(InvocationHandler handler) {
+ protected Proxy(InvocationHandler handler)
+ {
if (handler == null && isProxyClass(getClass()))
throw new NullPointerException("invalid handler");
h = handler;
}
/**
- * Returns the proxy {@link Class} for the given ClassLoader and array of
- * interfaces, dynamically generating it if necessary.
+ * Returns the proxy {@link Class} for the given ClassLoader and array
+ * of interfaces, dynamically generating it if necessary.
*
- * <p>
- * There are several restrictions on this method, the violation of which
- * will result in an IllegalArgumentException or NullPointerException:
- * </p>
+ * <p>There are several restrictions on this method, the violation of
+ * which will result in an IllegalArgumentException or
+ * NullPointerException:</p>
*
* <ul>
* <li>All objects in `interfaces' must represent distinct interfaces.
* Classes, primitive types, null, and duplicates are forbidden.</li>
- * <li>The interfaces must be visible in the specified ClassLoader. In
- * other words, for each interface i:
- * <code>Class.forName(i.getName(), false, loader) == i</code> must be
- * true.</li>
- * <li>All non-public interfaces (if any) must reside in the same package,
- * or the proxy class would be non-instantiable. If there are no non-public
- * interfaces, the package of the proxy class is unspecified.</li>
- * <li>All interfaces must be compatible - if two declare a method with the
- * same name and parameters, the return type must be the same and the throws
- * clause of the proxy class will be the maximal subset of subclasses of the
- * throws clauses for each method that is overridden.</li>
- * <li>VM constraints limit the number of interfaces a proxy class may
- * directly implement (however, the indirect inheritance of
- * {@link Serializable} does not count against this limit). Even though most
- * VMs can theoretically have 65535 superinterfaces for a class, the actual
- * limit is smaller because a class's constant pool is limited to 65535
- * entries, and not all entries can be interfaces.</li>
+ * <li>The interfaces must be visible in the specified ClassLoader.
+ * In other words, for each interface i:
+ * <code>Class.forName(i.getName(), false, loader) == i</code>
+ * must be true.</li>
+ * <li>All non-public interfaces (if any) must reside in the same
+ * package, or the proxy class would be non-instantiable. If
+ * there are no non-public interfaces, the package of the proxy
+ * class is unspecified.</li>
+ * <li>All interfaces must be compatible - if two declare a method
+ * with the same name and parameters, the return type must be
+ * the same and the throws clause of the proxy class will be
+ * the maximal subset of subclasses of the throws clauses for
+ * each method that is overridden.</li>
+ * <li>VM constraints limit the number of interfaces a proxy class
+ * may directly implement (however, the indirect inheritance
+ * of {@link Serializable} does not count against this limit).
+ * Even though most VMs can theoretically have 65535
+ * superinterfaces for a class, the actual limit is smaller
+ * because a class's constant pool is limited to 65535 entries,
+ * and not all entries can be interfaces.</li>
* </ul>
*
- * <p>
- * Note that different orders of interfaces produce distinct classes.
- * </p>
- *
- * @param loader
- * the class loader to define the proxy class in; null implies
- * the bootstrap class loader
- * @param interfaces
- * the array of interfaces the proxy class implements, may be
- * empty, but not null
+ * <p>Note that different orders of interfaces produce distinct classes.</p>
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the array of interfaces the proxy class implements,
+ * may be empty, but not null
* @return the Class object of the proxy class
- * @throws IllegalArgumentException
- * if the constraints above were violated, except for problems
- * with null
- * @throws NullPointerException
- * if `interfaces' is null or contains a null entry
+ * @throws IllegalArgumentException if the constraints above were
+ * violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry
*/
// synchronized so that we aren't trying to build the same class
// simultaneously in two threads
public static synchronized Class getProxyClass(ClassLoader loader,
- Class[] interfaces) {
+ Class[] interfaces)
+ {
interfaces = (Class[]) interfaces.clone();
ProxyType pt = new ProxyType(loader, interfaces);
Class clazz = (Class) proxyClasses.get(pt);
- if (clazz == null) {
+ if (clazz == null)
+ {
if (VMProxy.HAVE_NATIVE_GET_PROXY_CLASS)
clazz = VMProxy.getProxyClass(loader, interfaces);
- else {
- ProxyData data = (VMProxy.HAVE_NATIVE_GET_PROXY_DATA ? VMProxy
- .getProxyData(loader, interfaces) : ProxyData
- .getProxyData(pt));
+ else
+ {
+ ProxyData data = (VMProxy.HAVE_NATIVE_GET_PROXY_DATA
+ ? VMProxy.getProxyData(loader, interfaces)
+ : ProxyData.getProxyData(pt));
- clazz = (VMProxy.HAVE_NATIVE_GENERATE_PROXY_CLASS ? VMProxy
- .generateProxyClass(loader, data) : new ClassFactory(
- data).generate(loader));
+ clazz = (VMProxy.HAVE_NATIVE_GENERATE_PROXY_CLASS
+ ? VMProxy.generateProxyClass(loader, data)
+ : new ClassFactory(data).generate(loader));
}
Object check = proxyClasses.put(pt, clazz);
// assert check == null && clazz != null;
if (check != null || clazz == null)
- throw new InternalError(/* "Fatal flaw in getProxyClass" */);
+ throw new InternalError(/*"Fatal flaw in getProxyClass"*/);
}
return clazz;
}
/**
* Combines several methods into one. This is equivalent to:
- *
* <pre>
- * Proxy.getProxyClass(loader, interfaces).getConstructor(
- * new Class[] { InvocationHandler.class }).newInstance(
- * new Object[] { handler });
+ * Proxy.getProxyClass(loader, interfaces)
+ * .getConstructor(new Class[] {InvocationHandler.class})
+ * .newInstance(new Object[] {handler});
* </pre>
+ * except that it will not fail with the normal problems caused
+ * by reflection. It can still fail for the same reasons documented
+ * in getProxyClass, or if handler is null.
*
- * except that it will not fail with the normal problems caused by
- * reflection. It can still fail for the same reasons documented in
- * getProxyClass, or if handler is null.
- *
- * @param loader
- * the class loader to define the proxy class in; null implies
- * the bootstrap class loader
- * @param interfaces
- * the array of interfaces the proxy class implements, may be
- * empty, but not null
- * @param handler
- * the invocation handler, may not be null
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the array of interfaces the proxy class implements,
+ * may be empty, but not null
+ * @param handler the invocation handler, may not be null
* @return a proxy instance implementing the specified interfaces
- * @throws IllegalArgumentException
- * if the constraints for getProxyClass were violated, except
- * for problems with null
- * @throws NullPointerException
- * if `interfaces' is null or contains a null entry, or if
- * handler is null
+ * @throws IllegalArgumentException if the constraints for getProxyClass
+ * were violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry, or if handler is null
* @see #getProxyClass(ClassLoader, Class[])
* @see Class#getConstructor(Class[])
* @see Constructor#newInstance(Object[])
*/
public static Object newProxyInstance(ClassLoader loader,
- Class[] interfaces, InvocationHandler handler) {
- try {
+ Class[] interfaces,
+ InvocationHandler handler)
+ {
+ try
+ {
// getProxyClass() and Proxy() throw the necessary exceptions
- return getProxyClass(loader, interfaces).getConstructor(
- new Class[] { InvocationHandler.class }).newInstance(
- new Object[] { handler });
- } catch (RuntimeException e) {
+ return getProxyClass(loader, interfaces)
+ .getConstructor(new Class[] {InvocationHandler.class})
+ .newInstance(new Object[] {handler});
+ }
+ catch (RuntimeException e)
+ {
// Let IllegalArgumentException, NullPointerException escape.
// assert e instanceof IllegalArgumentException
// || e instanceof NullPointerException;
throw e;
- } catch (InvocationTargetException e) {
+ }
+ catch (InvocationTargetException e)
+ {
// Let wrapped NullPointerException escape.
// assert e.getTargetException() instanceof NullPointerException
throw (NullPointerException) e.getCause();
- } catch (Exception e) {
+ }
+ catch (Exception e)
+ {
// Covers InstantiationException, IllegalAccessException,
// NoSuchMethodException, none of which should be generated
// if the proxy class was generated correctly.
@@ -339,24 +347,22 @@
/**
* Returns true if and only if the Class object is a dynamically created
- * proxy class (created by <code>getProxyClass</code> or by the syntactic
- * sugar of <code>newProxyInstance</code>).
+ * proxy class (created by <code>getProxyClass</code> or by the
+ * syntactic sugar of <code>newProxyInstance</code>).
*
- * <p>
- * This check is secure (in other words, it is not simply
- * <code>clazz.getSuperclass() == Proxy.class</code>), it will not be
- * spoofed by non-proxy classes that extend Proxy.
+ * <p>This check is secure (in other words, it is not simply
+ * <code>clazz.getSuperclass() == Proxy.class</code>), it will not
+ * be spoofed by non-proxy classes that extend Proxy.
*
- * @param clazz
- * the class to check, must not be null
+ * @param clazz the class to check, must not be null
* @return true if the class represents a proxy class
- * @throws NullPointerException
- * if clazz is null
+ * @throws NullPointerException if clazz is null
*/
// This is synchronized on the off chance that another thread is
// trying to add a class to the map at the same time we read it.
- public static synchronized boolean isProxyClass(Class clazz) {
- if (!Proxy.class.isAssignableFrom(clazz))
+ public static synchronized boolean isProxyClass(Class clazz)
+ {
+ if (! Proxy.class.isAssignableFrom(clazz))
return false;
// This is a linear search, even though we could do an O(1) search
// using new ProxyType(clazz.getClassLoader(), clazz.getInterfaces()).
@@ -364,35 +370,33 @@
}
/**
- * Returns the invocation handler for the given proxy instance.
- * <p>
+ * Returns the invocation handler for the given proxy instance.<p>
*
- * <em>NOTE</em>: We guarantee a non-null result if successful, but Sun
- * allows the creation of a proxy instance with a null handler. See the
- * comments for {@link #Proxy(InvocationHandler)}.
+ * <em>NOTE</em>: We guarantee a non-null result if successful,
+ * but Sun allows the creation of a proxy instance with a null
+ * handler. See the comments for {@link #Proxy(InvocationHandler)}.
*
- * @param proxy
- * the proxy instance, must not be null
+ * @param proxy the proxy instance, must not be null
* @return the invocation handler, guaranteed non-null.
- * @throws IllegalArgumentException
- * if <code>Proxy.isProxyClass(proxy.getClass())</code>
- * returns false.
- * @throws NullPointerException
- * if proxy is null
+ * @throws IllegalArgumentException if
+ * <code>Proxy.isProxyClass(proxy.getClass())</code> returns false.
+ * @throws NullPointerException if proxy is null
*/
- public static InvocationHandler getInvocationHandler(Object proxy) {
- if (!isProxyClass(proxy.getClass()))
+ public static InvocationHandler getInvocationHandler(Object proxy)
+ {
+ if (! isProxyClass(proxy.getClass()))
throw new IllegalArgumentException("not a proxy instance");
return ((Proxy) proxy).h;
}
/**
- * Helper class for mapping unique ClassLoader and interface combinations to
- * proxy classes.
+ * Helper class for mapping unique ClassLoader and interface combinations
+ * to proxy classes.
*
* @author Eric Blake (eb...@em...)
*/
- private static final class ProxyType {
+ private static final class ProxyType
+ {
/**
* Store the class loader (may be null)
*/
@@ -406,13 +410,12 @@
/**
* Construct the helper object.
*
- * @param loader
- * the class loader to define the proxy class in; null
+ * @param loader the class loader to define the proxy class in; null
* implies the bootstrap class loader
- * @param interfaces
- * an array of interfaces
+ * @param interfaces an array of interfaces
*/
- ProxyType(ClassLoader loader, Class[] interfaces) {
+ ProxyType(ClassLoader loader, Class[] interfaces)
+ {
this.loader = loader;
this.interfaces = interfaces;
}
@@ -422,7 +425,8 @@
*
* @return a combination of the classloader and interfaces hashcodes.
*/
- public int hashCode() {
+ public int hashCode()
+ {
int hash = loader == null ? 0 : loader.hashCode();
for (int i = 0; i < interfaces.length; i++)
hash = hash * 31 + interfaces[i].hashCode();
@@ -432,14 +436,13 @@
/**
* Calculates equality.
*
- * @param other
- * object to compare to
+ * @param other object to compare to
* @return true if it is a ProxyType with same data
*/
- public boolean equals(Object other) {
+ public boolean equals(Object other)
+ {
ProxyType pt = (ProxyType) other;
- if (loader != pt.loader
- || interfaces.length != pt.interfaces.length)
+ if (loader != pt.loader || interfaces.length != pt.interfaces.length)
return false;
for (int i = 0; i < interfaces.length; i++)
if (interfaces[i] != pt.interfaces[i])
@@ -449,32 +452,36 @@
} // class ProxyType
/**
- * Helper class which allows hashing of a method name and signature without
- * worrying about return type, declaring class, or throws clause, and which
- * reduces the maximally common throws clause between two methods
+ * Helper class which allows hashing of a method name and signature
+ * without worrying about return type, declaring class, or throws clause,
+ * and which reduces the maximally common throws clause between two methods
*
* @author Eric Blake (eb...@em...)
*/
- private static final class ProxySignature {
+ private static final class ProxySignature
+ {
/**
* The core signatures which all Proxy instances handle.
*/
static final HashMap coreMethods = new HashMap();
- static {
- try {
- ProxySignature sig = new ProxySignature(Object.class.getMethod(
- "equals", new Class[] { Object.class }));
+ static
+ {
+ try
+ {
+ ProxySignature sig
+ = new ProxySignature(Object.class
+ .getMethod("equals",
+ new Class[] {Object.class}));
coreMethods.put(sig, sig);
- sig = new ProxySignature(Object.class.getMethod("hashCode",
- null));
+ sig = new ProxySignature(Object.class.getMethod("hashCode", null));
coreMethods.put(sig, sig);
- sig = new ProxySignature(Object.class.getMethod("toString",
- null));
+ sig = new ProxySignature(Object.class.getMethod("toString", null));
coreMethods.put(sig, sig);
- } catch (Exception e) {
+ }
+ catch (Exception e)
+ {
// assert false;
- throw (Error) new InternalError("Unexpected: " + e)
- .initCause(e);
+ throw (Error) new InternalError("Unexpected: " + e).initCause(e);
}
}
@@ -491,14 +498,15 @@
/**
* Construct a signature
*
- * @param method
- * the Method this signature is based on, never null
+ * @param method the Method this signature is based on, never null
*/
- ProxySignature(Method method) {
+ ProxySignature(Method method)
+ {
this.method = method;
Class[] exc = method.getExceptionTypes();
int i = exc.length;
- while (--i >= 0) {
+ while (--i >= 0)
+ {
// discard unchecked exceptions
if (Error.class.isAssignableFrom(exc[i])
|| RuntimeException.class.isAssignableFrom(exc[i]))
@@ -508,19 +516,17 @@
}
/**
- * Given a method, make sure it's return type is identical to this, and
- * adjust this signature's throws clause appropriately
+ * Given a method, make sure it's return type is identical
+ * to this, and adjust this signature's throws clause appropriately
*
- * @param other
- * the signature to merge in
- * @throws IllegalArgumentException
- * if the return types conflict
+ * @param other the signature to merge in
+ * @throws IllegalArgumentException if the return types conflict
*/
- void checkCompatibility(ProxySignature other) {
+ void checkCompatibility(ProxySignature other)
+ {
if (method.getReturnType() != other.method.getReturnType())
- throw new IllegalArgumentException(
- "incompatible return types: " + method + ", "
- + other.method);
+ throw new IllegalArgumentException("incompatible return types: "
+ + method + ", " + other.method);
// if you can think of a more efficient way than this O(n^2) search,
// implement it!
@@ -530,11 +536,13 @@
boolean[] valid2 = new boolean[size2];
Iterator itr = exceptions.iterator();
int pos = size1;
- while (--pos >= 0) {
+ while (--pos >= 0)
+ {
Class c1 = (Class) itr.next();
Iterator itr2 = other.exceptions.iterator();
int pos2 = size2;
- while (--pos2 >= 0) {
+ while (--pos2 >= 0)
+ {
Class c2 = (Class) itr2.next();
if (c2.isAssignableFrom(c1))
valid1[pos] = true;
@@ -544,16 +552,18 @@
}
pos = size1;
itr = exceptions.iterator();
- while (--pos >= 0) {
+ while (--pos >= 0)
+ {
itr.next();
- if (!valid1[pos])
+ if (! valid1[pos])
itr.remove();
}
pos = size2;
itr = other.exceptions.iterator();
- while (--pos >= 0) {
+ while (--pos >= 0)
+ {
itr.next();
- if (!valid2[pos])
+ if (! valid2[pos])
itr.remove();
}
exceptions.addAll(other.exceptions);
@@ -564,7 +574,8 @@
*
* @return a combination of name and parameter types
*/
- public int hashCode() {
+ public int hashCode()
+ {
int hash = method.getName().hashCode();
Class[] types = method.getParameterTypes();
for (int i = 0; i < types.length; i++)
@@ -575,15 +586,15 @@
/**
* Calculates equality.
*
- * @param other
- * object to compare to
+ * @param other object to compare to
* @return true if it is a ProxySignature with same data
*/
- public boolean equals(Object other) {
+ public boolean equals(Object other)
+ {
ProxySignature ps = (ProxySignature) other;
Class[] types1 = method.getParameterTypes();
Class[] types2 = ps.method.getParameterTypes();
- if (!method.getName().equals(ps.method.getName())
+ if (! method.getName().equals(ps.method.getName())
|| types1.length != types2.length)
return false;
int i = types1.length;
@@ -600,10 +611,11 @@
*
* @author Eric Blake (eb...@em...)
*/
- static final class ProxyData {
+ static final class ProxyData
+ {
/**
- * The package this class is in <b>including the trailing dot</b> or an
- * empty string for the unnamed (aka default) package.
+ * The package this class is in <b>including the trailing dot</b>
+ * or an empty string for the unnamed (aka default) package.
*/
String pack = "";
@@ -615,8 +627,8 @@
/**
* The Method objects this class must pass as the second argument to
* invoke (also useful for determining what methods this class has).
- * Non-null, non-empty (includes at least Object.hashCode,
- * Object.equals, and Object.toString).
+ * Non-null, non-empty (includes at least Object.hashCode, Object.equals,
+ * and Object.toString).
*/
Method[] methods;
@@ -624,8 +636,8 @@
* The exceptions that do not need to be wrapped in
* UndeclaredThrowableException. exceptions[i] is the same as, or a
* subset of subclasses, of methods[i].getExceptionTypes(), depending on
- * compatible throws clauses with multiple inheritance. It is
- * unspecified if these lists include or exclude subclasses of Error and
+ * compatible throws clauses with multiple inheritance. It is unspecified
+ * if these lists include or exclude subclasses of Error and
* RuntimeException, but excluding them is harmless and generates a
* smaller class.
*/
@@ -644,16 +656,19 @@
/**
* Construct a ProxyData with uninitialized data members.
*/
- ProxyData() {
+ ProxyData()
+ {
}
/**
- * Return the name of a package (including the trailing dot) given the
- * name of a class. Returns an empty string if no package. We use this
- * in preference to using Class.getPackage() to avoid problems with
- * ClassLoaders that don't set the package.
+ * Return the name of a package (including the trailing dot)
+ * given the name of a class.
+ * Returns an empty string if no package. We use this in preference to
+ * using Class.getPackage() to avoid problems with ClassLoaders
+ * that don't set the package.
*/
- private static String getPackage(Class k) {
+ private static String getPackage(Class k)
+ {
String name = k.getName();
int idx = name.lastIndexOf('.');
return name.substring(0, idx + 1);
@@ -661,23 +676,20 @@
/**
* Verifies that the arguments are legal, and sets up remaining data
- * This should only be called when a class must be generated, as it is
- * expensive.
+ * This should only be called when a class must be generated, as
+ * it is expensive.
*
- * @param pt
- * the ProxyType to convert to ProxyData
- * @return the flattened, verified ProxyData structure for use in class
- * generation
- * @throws IllegalArgumentException
- * if `interfaces' contains non-interfaces or incompatible
- * combinations, and verify is true
- * @throws NullPointerException
- * if interfaces is null or contains null
+ * @param pt the ProxyType to convert to ProxyData
+ * @return the flattened, verified ProxyData structure for use in
+ * class generation
+ * @throws IllegalArgumentException if `interfaces' contains
+ * non-interfaces or incompatible combinations, and verify is true
+ * @throws NullPointerException if interfaces is null or contains null
*/
- static ProxyData getProxyData(ProxyType pt) {
+ static ProxyData getProxyData(ProxyType pt)
+ {
Map method_set = (Map) ProxySignature.coreMethods.clone();
- boolean in_package = false; // true if we encounter non-public
- // interface
+ boolean in_package = false; // true if we encounter non-public interface
ProxyData data = new ProxyData();
data.interfaces = pt.interfaces;
@@ -685,46 +697,52 @@
// if interfaces is too large, we croak later on when the constant
// pool overflows
int i = data.interfaces.length;
- while (--i >= 0) {
+ while (--i >= 0)
+ {
Class inter = data.interfaces[i];
- if (!inter.isInterface())
- throw new IllegalArgumentException("not an interface: "
- + inter);
- try {
+ if (! inter.isInterface())
+ throw new IllegalArgumentException("not an interface: " + inter);
+ try
+ {
if (Class.forName(inter.getName(), false, pt.loader) != inter)
throw new IllegalArgumentException("not accessible in "
+ "classloader: " + inter);
- } catch (ClassNotFoundException e) {
+ }
+ catch (ClassNotFoundException e)
+ {
throw new IllegalArgumentException("not accessible in "
+ "classloader: " + inter);
}
- if (!Modifier.isPublic(inter.getModifiers()))
- if (in_package) {
+ if (! Modifier.isPublic(inter.getModifiers()))
+ if (in_package)
+ {
String p = getPackage(inter);
- if (!data.pack.equals(p))
- throw new IllegalArgumentException(
- "non-public interfaces "
- + "from different " + "packages");
- } else {
+ if (! data.pack.equals(p))
+ throw new IllegalArgumentException("non-public interfaces "
+ + "from different "
+ + "packages");
+ }
+ else
+ {
in_package = true;
data.pack = getPackage(inter);
}
- for (int j = i - 1; j >= 0; j--)
+ for (int j = i-1; j >= 0; j--)
if (data.interfaces[j] == inter)
- throw new IllegalArgumentException(
- "duplicate interface: " + inter);
+ throw new IllegalArgumentException("duplicate interface: "
+ + inter);
Method[] methods = inter.getMethods();
int j = methods.length;
- while (--j >= 0) {
- if (isCoreObjectMethod(methods[j])) {
- // In the case of an attempt to redefine a public
- // non-final
+ while (--j >= 0)
+ {
+ if (isCoreObjectMethod(methods[j]))
+ {
+ // In the case of an attempt to redefine a public non-final
// method of Object, we must skip it
continue;
}
ProxySignature sig = new ProxySignature(methods[j]);
- ProxySignature old = (ProxySignature) method_set.put(sig,
- sig);
+ ProxySignature old = (ProxySignature) method_set.put(sig, sig);
if (old != null)
sig.checkCompatibility(old);
}
@@ -734,7 +752,8 @@
data.methods = new Method[i];
data.exceptions = new Class[i][];
Iterator itr = method_set.values().iterator();
- while (--i >= 0) {
+ while (--i >= 0)
+ {
ProxySignature sig = (ProxySignature) itr.next();
data.methods[i] = sig.method;
data.exceptions[i] = (Class[]) sig.exceptions
@@ -745,30 +764,33 @@
/**
* Checks whether the method is similar to a public non-final method of
- * Object or not (i.e. with the same name and parameter types). Note
- * that we can't rely, directly or indirectly (via Collection.contains)
- * on Method.equals as it would also check the declaring class, what we
- * do not want. We only want to check that the given method have the
- * same signature as a core method (same name and parameter types)
+ * Object or not (i.e. with the same name and parameter types). Note that we
+ * can't rely, directly or indirectly (via Collection.contains) on
+ * Method.equals as it would also check the declaring class, what we do not
+ * want. We only want to check that the given method have the same signature
+ * as a core method (same name and parameter types)
*
- * @param method
- * the method to check
+ * @param method the method to check
* @return whether the method has the same name and parameter types as
* Object.equals, Object.hashCode or Object.toString
* @see java.lang.Object#equals(Object)
* @see java.lang.Object#hashCode()
* @see java.lang.Object#toString()
*/
- private static boolean isCoreObjectMethod(Method method) {
+ private static boolean isCoreObjectMethod(Method method)
+ {
String methodName = method.getName();
- if (methodName.equals("equals")) {
+ if (methodName.equals("equals"))
+ {
return Arrays.equals(method.getParameterTypes(),
new Class[] { Object.class });
}
- if (methodName.equals("hashCode")) {
+ if (methodName.equals("hashCode"))
+ {
return method.getParameterTypes().length == 0;
}
- if (methodName.equals("toString")) {
+ if (methodName.equals("toString"))
+ {
return method.getParameterTypes().length == 0;
}
return false;
@@ -778,92 +800,59 @@
/**
* Does all the work of building a class. By making this a nested class,
- * this code is not loaded in memory if the VM has a native implementation
- * instead.
+ * this code is not loaded in memory if the VM has a native
+ * implementation instead.
*
* @author Eric Blake (eb...@em...)
*/
- private static final class ClassFactory {
+ private static final class ClassFactory
+ {
/** Constants for assisting the compilation */
private static final byte FIELD = 1;
-
private static final byte METHOD = 2;
-
private static final byte INTERFACE = 3;
-
- private static final String CTOR_SIG = "(Ljava/lang/reflect/InvocationHandler;)V";
-
+ private static final String CTOR_SIG
+ = "(Ljava/lang/reflect/InvocationHandler;)V";
private static final String INVOKE_SIG = "(Ljava/lang/Object;"
+ "Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";
/** Bytecodes for insertion in the class definition byte[] */
private static final char ACONST_NULL = 1;
-
private static final char ICONST_0 = 3;
-
private static final char BIPUSH = 16;
-
private static final char SIPUSH = 17;
-
private static final char ILOAD = 21;
-
private static final char ILOAD_0 = 26;
-
private static final char ALOAD_0 = 42;
-
private static final char ALOAD_1 = 43;
-
private static final char AALOAD = 50;
-
private static final char AASTORE = 83;
-
private static final char DUP = 89;
-
private static final char DUP_X1 = 90;
-
private static final char SWAP = 95;
-
private static final char IRETURN = 172;
-
private static final char LRETURN = 173;
-
private static final char FRETURN = 174;
-
private static final char DRETURN = 175;
-
private static final char ARETURN = 176;
-
private static final char RETURN = 177;
-
private static final char GETSTATIC = 178;
-
private static final char GETFIELD = 180;
-
private static final char INVOKEVIRTUAL = 182;
-
private static final char INVOKESPECIAL = 183;
-
private static final char INVOKEINTERFACE = 185;
-
private static final char NEW = 187;
-
private static final char ANEWARRAY = 189;
-
private static final char ATHROW = 191;
-
private static final char CHECKCAST = 192;
- private static final char POP = 87;
-
- // Implementation note: we use StringBuffers to hold the byte data,
- // since
+ // Implementation note: we use StringBuffers to hold the byte data, since
// they automatically grow. However, we only use the low 8 bits of
// every char in the array, so we are using twice the necessary memory
// for the ease StringBuffer provides.
/** The constant pool. */
private final StringBuffer pool = new StringBuffer();
-
/** The rest of the class data. */
private final StringBuffer stream = new StringBuffer();
@@ -882,15 +871,14 @@
/**
* Initializes the buffers with the bytecode contents for a proxy class.
*
- * @param data
- * the remainder of the class data
- * @throws IllegalArgumentException
- * if anything else goes wrong this late in the game; as far
- * as I can tell, this will only happen if the constant pool
- * overflows, which is possible even when the user doesn't
- * exceed the 65535 interface limit
+ * @param data the remainder of the class data
+ * @throws IllegalArgumentException if anything else goes wrong this
+ * late in the game; as far as I can tell, this will only happen
+ * if the constant pool overflows, which is possible even when
+ * the user doesn't exceed the 65535 interface limit
*/
- ClassFactory(ProxyData data) {
+ ClassFactory(ProxyData data)
+ {
methods = data.methods;
// magic = 0xcafebabe
@@ -901,7 +889,7 @@
// constant_pool[], filled in as we go
// access_flags
- putU2(Modifier.SUPER | Modifier.FINAL | Modifier.PUBLIC);
+ putU2(/*Modifier.SUPER |*/ Modifier.FINAL | Modifier.PUBLIC);
// this_class
qualName = (data.pack + "$Proxy" + data.id);
putU2(classInfo(TypeSignature.getEncodingOfClass(qualName, false)));
@@ -916,8 +904,7 @@
// Recall that Proxy classes serialize specially, so we do not need
// to worry about a <clinit> method for this field. Instead, we
- // just assign it by reflection after the class is successfully
- // loaded.
+ // just assign it by reflection after the class is successfully loaded.
// fields_count - private static Method[] m;
putU2(1);
// fields[]
@@ -972,37 +959,39 @@
/**
* Produce the bytecode for a single method.
*
- * @param i
- * the index of the method we are building
- * @param e
- * the exceptions possible for the method
+ * @param i the index of the method we are building
+ * @param e the exceptions possible for the method
*/
- private void emitMethod(int i, Class[] e) {
+ private void emitMethod(int i, Class[] e)
+ {
// First, we precalculate the method length and other information.
Method m = methods[i];
Class[] paramtypes = m.getParameterTypes();
int wrap_overhead = 0; // max words taken by wrapped primitive
int param_count = 1; // 1 for this
- int code_length = 16; // aload_0, getfield, aload_0, getstatic,
- // const,
+ int code_length = 16; // aload_0, getfield, aload_0, getstatic, const,
// aaload, const/aconst_null, invokeinterface
- if (i > 5) {
+ if (i > 5)
+ {
if (i > Byte.MAX_VALUE)
code_length += 2; // sipush
else
code_length++; // bipush
}
- if (paramtypes.length > 0) {
+ if (paramtypes.length > 0)
+ {
code_length += 3; // anewarray
if (paramtypes.length > Byte.MAX_VALUE)
code_length += 2; // sipush
else if (paramtypes.length > 5)
code_length++; // bipush
- for (int j = 0; j < paramtypes.length; j++) {
+ for (int j = 0; j < paramtypes.length; j++)
+ {
code_length += 4; // dup, const, load, store
Class type = paramtypes[j];
- if (j > 5) {
+ if (j > 5)
+ {
if (j > Byte.MAX_VALUE)
code_length += 2; // sipush
else
@@ -1011,22 +1000,23 @@
if (param_count >= 4)
code_length++; // 2-byte load
param_count++;
- if (type.isPrimitive()) {
+ if (type.isPrimitive())
+ {
code_length += 7; // new, dup, invokespecial
- if (type == long.class || type == double.class) {
+ if (type == long.class || type == double.class)
+ {
wrap_overhead = 3;
param_count++;
- } else if (wrap_overhead < 2)
+ }
+ else if (wrap_overhead < 2)
wrap_overhead = 2;
}
}
}
int end_pc = code_length;
Class ret_type = m.getReturnType();
- if (ret_type == void.class) {
- code_length++; // pop
+ if (ret_type == void.class)
code_length++; // return
- }
else if (ret_type.isPrimitive())
code_length += 7; // cast, invokevirtual, return
else
@@ -1034,22 +1024,21 @@
int exception_count = 0;
boolean throws_throwable = false;
for (int j = 0; j < e.length; j++)
- if (e[j] == Throwable.class) {
+ if (e[j] == Throwable.class)
+ {
throws_throwable = true;
break;
}
- if (!throws_throwable) {
- exception_count = e.length + 3; // Throwable, Error,
- // RuntimeException
+ if (! throws_throwable)
+ {
+ exception_count = e.length + 3; // Throwable, Error, RuntimeException
code_length += 9; // new, dup_x1, swap, invokespecial, athrow
}
int handler_pc = code_length - 1;
StringBuffer signature = new StringBuffer("(");
for (int j = 0; j < paramtypes.length; j++)
- signature.append(TypeSignature
- .getEncodingOfClass(paramtypes[j]));
- signature.append(")").append(
- TypeSignature.getEncodingOfClass(ret_type));
+ signature.append(TypeSignature.getEncodingOfClass(paramtypes[j]));
+ signature.append(")").append(TypeSignature.getEncodingOfClass(ret_type));
// Now we have enough information to emit the method.
@@ -1096,56 +1085,58 @@
"Ljava/lang/reflect/InvocationHandler;"));
putU1(ALOAD_0);
putU1(GETSTATIC);
- putU2(refInfo(FIELD, TypeSignature.getEncodingOfClass(qualName,
- false), "m", "[Ljava/lang/reflect/Method;"));
+ putU2(refInfo(FIELD, TypeSignature.getEncodingOfClass(qualName, false),
+ "m", "[Ljava/lang/reflect/Method;"));
putConst(i);
putU1(AALOAD);
- if (paramtypes.length > 0) {
+ if (paramtypes.length > 0)
+ {
putConst(paramtypes.length);
putU1(ANEWARRAY);
putU2(classInfo("java/lang/Object"));
param_count = 1;
- for (int j = 0; j < paramtypes.length; j++, param_count++) {
+ for (int j = 0; j < paramtypes.length; j++, param_count++)
+ {
putU1(DUP);
putConst(j);
- if (paramtypes[j].isPrimitive()) {
+ if (paramtypes[j].isPrimitive())
+ {
putU1(NEW);
putU2(classInfo(wrapper(paramtypes[j])));
putU1(DUP);
}
putLoad(param_count, paramtypes[j]);
- if (paramtypes[j].isPrimitive()) {
+ if (paramtypes[j].isPrimitive())
+ {
...
[truncated message content] |