United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-7058630 JSR 292 method handle proxy violates contract for Object methods
JDK-7058630 : JSR 292 method handle proxy violates contract for Object methods

Details
Type:
Bug
Submit Date:
2011-06-23
Status:
Closed
Updated Date:
2013-08-07
Project Name:
JDK
Resolved Date:
2011-08-02
Component:
core-libs
OS:
generic
Sub-Component:
java.lang.invoke
CPU:
generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
7
Fixed Versions:

Related Reports
Backport:
Backport:
Backport:
Relates:

Sub Tasks

Description
import java.lang.invoke.*;
import java.util.Arrays;

class BadProxy {
    private static void run() {
        System.out.println("hello, world");
    }
    public static void main(String... av) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandle run = lookup.findStatic(lookup.lookupClass(), "run", MethodType.methodType(void.class));
        Runnable r = MethodHandleProxies.asInterfaceInstance(Runnable.class, run);
        testRunnable(r);
    }
    private static void testRunnable(Runnable r) {
        r.run();
        Object o = r;
        boolean eq = (o == o);
        int     hc = System.identityHashCode(o);
        String  st = o.getClass().getName() + "@" + Integer.toHexString(hc);
        Object expect = Arrays.asList(st, eq, hc);
        System.out.println("expect st/eq/hc = "+expect);
        Object actual = Arrays.asList(o.toString(), o.equals(o), o.hashCode());
        System.out.println("actual st/eq/hc = "+actual);
        if (!expect.equals(actual))  throw new AssertionError(expect+" != "+actual);
    }
}
/*
Bug:

hello, world
expect st/eq/hc = [$Proxy0@58431c, true, 5784348]
actual st/eq/hc = [java.lang.invoke.MethodHandleProxies$1@9e0c79, false, 10357881]
Exception in thread "main" java.lang.AssertionError: [$Proxy0@58431c, true, 5784348] != [java.lang.invoke.MethodHandleProxies$1@9e0c79, false, 10357881]
	at BadProxy.testRunnable(BadProxy.java:24)
	at BadProxy.main(BadProxy.java:12)

Expected:

hello, world
expect st/eq/hc = [$Proxy0@db81f3, true, 14385651]
actual st/eq/hc = [$Proxy0@db81f3, true, 14385651]

Fix:

diff --git a/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
--- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java
+++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
@@ -165,7 +165,7 @@
                         if (method.getDeclaringClass() == WrapperInstance.class)
                             return getArg(method.getName());
                         if (isObjectMethod(method))
-                            return callObjectMethod(this, method, args);
+                            return callObjectMethod(proxy, method, args);
                         throw new InternalError("bad proxy method: "+method);
                     }
                 }));

*/

                                    

Comments
SUGGESTED FIX

See description.
                                     
2011-06-23
WORK AROUND

Don't use object methods on proxies.  Such usage is rare.

Avoid putting them in java.util.Collections, which use the Object.equals method for Collection.contains, etc.
                                     
2011-06-23
EVALUATION

yes
                                     
2011-06-23
http://hg.openjdk.java.net/jdk8/tl/jdk/rev/bfc5ec581c48
                                     
2013-08-07



Hardware and Software, Engineered to Work Together