2009/6/18 Regis <xu.re...@gmail.com> > Jim Yu wrote: > >> 2009/6/18 Regis <xu.re...@gmail.com> >> >> Jim Yu wrote: >>> >>> Hi all, >>>> >>>> There is an interesting edge case in HashMap. If we use a proxy object >>>> as >>>> the key to put something into HashMap, we will fail to retrieve the >>>> value >>>> by >>>> using that key. But RI works well for this case. Here is a test case >>>> below >>>> to present the problem. I found the root cause of the failure for our >>>> HashMap is that proxyInstance.equals(proxyInstance) returns false which >>>> sounds strange but appears work correctly as both Harmony and RI behave >>>> so. >>>> >>>> It's very interesting behaviors, seems like RI did it intended, are >>> there >>> any cases we need proxyInstance.equals(proxyInstance) return false? >>> >> >> >> I think it is reasonable to return false here since spec mentioned for >> proxy >> instance that "An invocation of the hashCode, equals, or toString methods >> declared in java.lang.Object on a proxy instance will be encoded and >> dispatched to the invocation handler's invoke method" So the meaning of >> equals method seems has been changed by the invoke here: ) >> >> >>> I suspect RI has made some special approaches to match the key when the >>> >>>> key >>>> is a proxy object. So I would be inclined to follow RI's behavior in >>>> this >>>> case. Any thoughts here? >>>> >>>> I think if proxyInstance.equals(proxyInstance) return false is >>> reasonable, >>> we should do some tricks to make HashMap work with Proxy. And does Proxy >>> object work well with other collections which used equals to retrieve >>> object >>> from collection? >>> >>> >> Agree. I have made a patch to do the trick so as to follow RI's behavior. >> > > The patch looks good for me, applied at r786015, please verify.
Verified at r786379. Thanks, Regis. > > > >> >> >>> I have raised a JIRA at >>>> https://issues.apache.org/jira/browse/HARMONY-6237for this issue. >>>> >>>> >>>> public interface MockInterface { >>>> public String mockMethod(); >>>> } >>>> >>>> public class MockClass implements MockInterface { >>>> public String mockMethod() { >>>> return "This is a mock class."; >>>> } >>>> } >>>> >>>> import java.lang.reflect.InvocationHandler; >>>> import java.lang.reflect.Method; >>>> import java.lang.reflect.Proxy; >>>> import java.util.HashMap; >>>> import java.util.Map; >>>> >>>> public class TestProxy implements InvocationHandler { >>>> >>>> Object obj; >>>> >>>> public TestProxy(Object o) { >>>> obj = o; >>>> } >>>> >>>> public Object invoke(Object proxy, Method m, Object[] args) >>>> throws Throwable { >>>> >>>> Object result = null; >>>> >>>> try { >>>> >>>> result = m.invoke(obj, args); >>>> >>>> } catch (Exception e) { >>>> e.printStackTrace(); >>>> } finally { >>>> } >>>> return result; >>>> } >>>> >>>> public static void main(String[] argv) throws Exception { >>>> >>>> MockInterface proxyInstance = (MockInterface) >>>> Proxy.newProxyInstance( >>>> MockInterface.class.getClassLoader(), >>>> new Class[] { MockInterface.class }, new TestProxy( >>>> new MockClass())); >>>> >>>> Map hm = new HashMap(); >>>> >>>> hm.put(proxyInstance, "Value"); >>>> >>>> Object o = hm.get(proxyInstance); >>>> >>>> System.out.println("Value got for proxy object key:" + o); >>>> >>>> System.out.println(proxyInstance.equals(proxyInstance)); >>>> >>>> } >>>> } >>>> >>>> Output >>>> Harmony: >>>> Value got for proxy object key:null >>>> false >>>> >>>> RI: >>>> Value got for proxy object key:Value >>>> false >>>> >>>> >>>> -- >>> Best Regards, >>> Regis. >>> >>> >> >> >> > > -- > Best Regards, > Regis. > -- Best Regards, Jim, Jun Jie Yu