JDK-8206955 : MethodHandleProxies.asInterfaceInstance does not support default methods
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 8,9,10,11
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2018-07-07
  • Updated: 2019-11-22
  • Resolved: 2018-08-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 12 Other
11.0.4Fixed 12 b06Fixed openjdk8u222Fixed
Related Reports
CSR :  
Description
A DESCRIPTION OF THE PROBLEM :
Calling a default method on an instance produced by MethodHandleProxies.asInterface throws a " java.lang.InternalError: bad proxy method: ...

This is a bug because it violates the contract of the default methods, e.g. java.util.Comparator.reversed().
Passing an interface with default methods is supported, as indicated in the documentation of MethodHandleProxies.asInterface, which mentions java.util.Comparator as example.

Therefore it is exprected that the resulting instance follows the contract of the default method, which could be done by calling the default implementation of that default method.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create an instance of an interface with at least one default method using MethodHandleProxies.asInterface(Class, MethodHandle).
Call a default method on that instance.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No exception is thrown.
ACTUAL -
An exception is thrown.

Exception in thread "main" java.lang.InternalError: bad proxy method: public default java.util.Comparator java.util.Comparator.reversed()
	at java.lang.invoke.MethodHandleStatics.newInternalError(MethodHandleStatics.java:124)
	at java.lang.invoke.MethodHandleProxies$1.invoke(MethodHandleProxies.java:193)
	at com.sun.proxy.$Proxy0.reversed(Unknown Source)
	at bug.BugMain.main(BugMain.java:15)

---------- BEGIN SOURCE ----------
package bug;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandleProxies;
import java.lang.invoke.MethodHandles;
import java.util.Comparator;

public class BugMain {
	public static void main(String[] args) {
		MethodHandle const0 = MethodHandles.constant(int.class, 0);
		MethodHandle compH = MethodHandles.dropArguments(const0, 0, Object.class, Object.class);
		Comparator<?> cmp = MethodHandleProxies.asInterfaceInstance(Comparator.class, compH);
		// cmp = (a, b) -> 0;
		cmp.reversed();
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Use the LambdaMetaFactory. This might not work for all cases and is more complicated than the simple MethodHandleProxy.

FREQUENCY : always



Comments
Fix Request, 11u. Patch applies cleanly, comes with its own test.
13-04-2019

Fix Request, 8u. Patch applies cleanly, comes with its own test.
12-04-2019

Additional information from submitter == The fact that j.l.i.MethodHandleProxies uses j.l.r.Proxy is an implementation detail, see also JDK-6983726 [1]. The supplied patch from Paul Sandoz uses a solution that is only possible in java.lang.invoke, using IMPL_LOOKUP. It would be nice if other code could also call default methods in their InvokationHandler. There is also the proposal from Peter Levart [2] (JDK-8159746 [3]) that adds public methods on j.l.r.Proxy to call default methods. Also, since Java 9 it appears that you can call the default method on any instance, see [4]. This solution does not work for unknown classes, because you still need a Lookup on something that implements that interface. I really hope that you consider applying Peter Levart's patch, maybe for Java 11. [1]: https://bugs.openjdk.java.net/browse/JDK-6983726 [2]: http://mail.openjdk.java.net/pipermail/core-libs-dev/2016-June/041629.html [3]: https://bugs.openjdk.java.net/browse/JDK-8159746 [4]: http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-January/010741.html
19-07-2018

http://cr.openjdk.java.net/~psandoz/jdk/JDK-8206955-mh-func-iface-proxy-default-methods/webrev/
10-07-2018

This issue is reprodcible in all the versions 8,9,10 and 11. Below is the error message executed on 11 ea b19 == -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+19/bin/javac BugMain.java -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+19/bin/java BugMain Exception in thread "main" java.lang.InternalError: bad proxy method: public default java.util.Comparator java.util.Comparator.reversed() at java.base/java.lang.invoke.MethodHandleStatics.newInternalError(MethodHandleStatics.java:108) at java.base/java.lang.invoke.MethodHandleProxies$1.invoke(MethodHandleProxies.java:195) at jdk.proxy1/com.sun.proxy.jdk.proxy1.$Proxy0.reversed(Unknown Source) at BugMain.main(BugMain.java:12)
10-07-2018