From dev-return-37479-apmail-harmony-dev-archive=harmony.apache.org@harmony.apache.org Thu Jun 18 08:31:02 2009 Return-Path: Delivered-To: apmail-harmony-dev-archive@www.apache.org Received: (qmail 37505 invoked from network); 18 Jun 2009 08:31:02 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 18 Jun 2009 08:31:02 -0000 Received: (qmail 96723 invoked by uid 500); 18 Jun 2009 08:31:13 -0000 Delivered-To: apmail-harmony-dev-archive@harmony.apache.org Received: (qmail 96627 invoked by uid 500); 18 Jun 2009 08:31:13 -0000 Mailing-List: contact dev-help@harmony.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@harmony.apache.org Delivered-To: mailing list dev@harmony.apache.org Received: (qmail 96606 invoked by uid 99); 18 Jun 2009 08:31:13 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 18 Jun 2009 08:31:13 +0000 X-ASF-Spam-Status: No, hits=2.2 required=10.0 tests=HTML_MESSAGE,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of junjie0122@gmail.com designates 209.85.216.187 as permitted sender) Received: from [209.85.216.187] (HELO mail-px0-f187.google.com) (209.85.216.187) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 18 Jun 2009 08:31:05 +0000 Received: by pxi17 with SMTP id 17so769058pxi.20 for ; Thu, 18 Jun 2009 01:30:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :date:message-id:subject:from:to:content-type; bh=TWRq39FVyvMrj6NcBqfLz4CyKwgXaVAxQm8vGEuN1F4=; b=e8IR0lKgGIdCKXGVlgB5K4HSVzLLMZjM0NtOM5kzOS59SLSUCOAQdvG5U7x3/Qvnc0 H5o9uU9/q0PT60Fj/bkJBtxBYG7tgSZ9HTuFzLFk2hUTpbTDxXkaWpfEzSxjjIGiduPq pL2jMGF4hRF2Sd/m/AmL2R8qPm1LEoxcv+wsU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; b=eGZgNgiu5fF2hr++GazHSjp24U6Ca0h8KAo2NmWdWk4hQwBpWDVEyfvD05yBejCFbt SuKFJ37Nydeu3ltRk29yC9mwPcdmkXRMB6hp+clnHPr6UPCF+TdPaDEcMPs1NUEmEVJu AhbzTwjnuLB7emgu2cChyvJlzeRbW7ieOrlOw= MIME-Version: 1.0 Received: by 10.114.175.16 with SMTP id x16mr1728762wae.98.1245313844860; Thu, 18 Jun 2009 01:30:44 -0700 (PDT) In-Reply-To: <4A39F2DE.60701@gmail.com> References: <4A39EAE6.2080502@gmail.com> <4A39F2DE.60701@gmail.com> Date: Thu, 18 Jun 2009 16:30:44 +0800 Message-ID: Subject: Re: [classlib][luni] HashMap doesn't support proxy object as keys From: Jim Yu To: dev@harmony.apache.org Content-Type: multipart/alternative; boundary=0016364589705b5b44046c9b392b X-Virus-Checked: Checked by ClamAV on apache.org --0016364589705b5b44046c9b392b Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit 2009/6/18 Regis > 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 list = new ArrayList(); > 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. Sounds interesting. It seems RI does use a special key matching mechanism for the HashMap if the key is proxy object. As HashSet is implemented based on HashMap, it is reasonable that HashSet will behave in the same way. And We will follow RI's behavior of HashSet as well after applying my patch for the HashMap. > > > >> >>> 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, Jim, Jun Jie Yu --0016364589705b5b44046c9b392b--