Hi,
I bumped into a major problem with spring and easymock which boiled
down to being a subtle definition of a Proxy. In the case of the
creation of a proxy which defines the same method as Object (which is
non final and public), the method in the interface must be so that
getDeclaringClass is Object.class and not the actual interface.
I just submitted a mauve testlet to stress this point and here is the
proposition of fix in Proxy.java (for non native Proxy implementations,
that's it). When iterating over the methods to be added to the proxy, if
any is matching an Object one (by its name and parameter types only), it
is skipped. Since we're already adding them automatically, it is not
missing of the resulting proxy and the declaring class remains Object.class
2006-02-19 Olivier Jolly <olivier.jolly>
* java/lang/reflect/Proxy.java
(ProxyData.getProxyData): Skipped overriding of core methods.
(ProxyData.isCoreObjectMethod): New method.
I have not yet passed the integrality of mauve tests to ensure
regression, but I will by the time this patch is accepted :)
Regards
Olivier
Index: Proxy.java
===================================================================
RCS file: /sources/classpath/classpath/java/lang/reflect/Proxy.java,v
retrieving revision 1.25
diff -u -r1.25 Proxy.java
--- Proxy.java 21 Oct 2005 00:30:28 -0000 1.25
+++ Proxy.java 19 Feb 2006 21:34:10 -0000
@@ -1,5 +1,5 @@
/* Proxy.java -- build a proxy class that implements reflected interfaces
- Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,6 +42,7 @@
import java.io.Serializable;
import java.security.ProtectionDomain;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -732,6 +733,12 @@
int j = methods.length;
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);
if (old != null)
@@ -752,6 +759,36 @@
}
return data;
}
+
+ /**
+ * Checks whether the method is a public non-final method of Object or not
+ *
+ * @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)
+ {
+ String methodName = method.getName();
+ if (methodName.equals("equals"))
+ {
+ return Arrays.equals(method.getParameterTypes(),
+ new Class[] { Object.class });
+ }
+ if (methodName.equals("hashCode"))
+ {
+ return method.getParameterTypes().length == 0;
+ }
+ if (methodName.equals("toString"))
+ {
+ return method.getParameterTypes().length == 0;
+ }
+ return false;
+ }
+
} // class ProxyData
/**