Regis wrote:
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 TestProxy is not implemented very well. spec said:

"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 in the same manner as interface method invocations are encoded and dispatched, as described above. "

So Proxy.equals will be dispatched to TestProxy and then to MockClass, but the argument of this invocation is a proxy instance, it never equals a MockClass instance.


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?

I tested ArrayList, Hashtable and HashSet:

        Map hm = new HashMap();
        hm.put(proxyInstance, proxyInstance);
        System.out.println(hm.containsKey(proxyInstance));
        System.out.println(hm.containsValue(proxyInstance));
        System.out.println();

        ArrayList<MockInterface> list = new ArrayList<MockInterface>();
        list.add(proxyInstance);
        System.out.println(list.contains(proxyInstance));
        System.out.println();

        Hashtable table = new Hashtable();
        table.put(proxyInstance, proxyInstance);
        System.out.println(table.containsKey(proxyInstance));
        System.out.println(table.containsValue(proxyInstance));
        System.out.println();

        HashSet set = new HashSet();
        set.add(proxyInstance);
        System.out.println(set.contains(proxyInstance));

the output of RI is:

true
false

false

false
false

true

seems RI doesn't use equals to retrieve keys in HashMap and values in HashSet.



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.

Reply via email to