JDK-8209078 : Unable to call default method from interface in another module from named module
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 10.0.2,11,12
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2018-08-03
  • Updated: 2019-08-19
  • Resolved: 2019-08-13
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 14
14 b10Fixed
Related Reports
Blocks :  
Relates :  
Description
A DESCRIPTION OF THE PROBLEM :
Unable to call default method from interface in an other module from named module.

Using Lookup.findSpecial it is possible to get a MethodHandle for the default method of an interface.
This only works if the code is in an unnamed module.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Try to find a MethodHandle for a default method of an interface in an other module from a named module.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
A MethodHandle for the default method is returned.
ACTUAL -
An exception is thrown.

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

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Method;
import java.util.Comparator;

public class ModuleFindDefault {
	private static final Lookup LOOKUP = MethodHandles.lookup();
	
	public static void main(String[] args) throws Throwable {
		Method method = Comparator.class.getMethod("reversed");
		Comparator<Object> cmp = new TestInterf();

		MethodHandle mhFind = findSpecial(method);
		Object findRev = mhFind.invoke(cmp);
		System.out.println(findRev);
	}
	
	static MethodHandle findSpecial(Method m) throws ReflectiveOperationException {
		return LOOKUP.findSpecial(m.getDeclaringClass(), m.getName(), 
				MethodType.methodType(m.getReturnType(), m.getParameterTypes()), 
				m.getDeclaringClass());
	}
	
	static class TestInterf implements Comparator<Object> {
		
		public int compare(Object o1, Object o2) {
			return 0;
		}
		
		@Override
		public Comparator<Object> reversed() {
			System.out.println("ModuleFindDefault.TestInterf.reversed()");
			return this;
		}
		
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Get somehow a private lookup in an unnamed module:

Create a ClassLoader, define a class, get the Lookup from this class?

FREQUENCY : always



Comments
URL: https://hg.openjdk.java.net/jdk/jdk/rev/7ba5e49258de User: mchung Date: 2019-08-13 22:49:27 +0000
13-08-2019

JDK-8173978 is resolved and so this issue is fixed. A new test will be added.
25-07-2019

Exception in thread "main" java.lang.IllegalAccessException: symbolic reference class is not accessible: interface java.util.Comparator, from java.util.Comparator/noaccess (module java.base) at java.base/java.lang.invoke.MemberName.makeAccessException(MemberName.java:942) at java.base/java.lang.invoke.MethodHandles$Lookup.checkSymbolicClass(MethodHandles.java:2060) at java.base/java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:2032) at java.base/java.lang.invoke.MethodHandles$Lookup.findSpecial(MethodHandles.java:1401) at bug/p.ModuleFindDefault.findSpecial(ModuleFindDefault.java:44) at bug/p.ModuleFindDefault.main(ModuleFindDefault.java:38) IAE is thrown because the implementation calls Lookup::in teleporting to a Lookup of the special class which lost all access since the caller class and the requested lookup class are in different modules. findSpecial and unreflectSpecial should behave consistently when the caller is unnamed module or named module.
13-09-2018

Additional information from submitter == Additional Information: > -sh-4.2$ /scratch/fairoz/JAVA/jdk12/jdk-12-ea+04/bin/javac -d modulepath module-info.java bug/ModuleFindDefault.java > -sh-4.2$ /scratch/fairoz/JAVA/jdk12/jdk-12-ea+04/bin/java -p modulepath -m bug/bug.ModuleFindDefault > Error occurred during initialization of boot layer > java.lang.module.FindException: Error reading module: modulepath > Caused by: java.lang.module.InvalidModuleDescriptorException: ModuleFindDefault.class found in top-level directory (unnamed package not allowed in module) It looks like ModuleFindDefault is still in the default package, maybe from an earlier compilation
08-08-2018

Here's a workaround. In the test replace m.getDeclaringClass() (which refers to the Comparator in the "java.base" module) with TestInterf.class (which is in the "bug" module). The invokespecial happens as if called from within the special caller and thus the lookup and the and the derived lookup for the special caller need to have appropriate capabilities. e.g. compare the capabilities of LOOKUP.in(Comparator.class) with LOOKUP or LOOKUP.in(TestInterf.class).
07-08-2018

Issue is reproducible in 9, 10, 11 and 12 -sh-4.2$ /scratch/fairoz/JAVA/jdk12/jdk-12-ea+04/bin/javac -d modulepath module-info.java bug/ModuleFindDefault.java -sh-4.2$ /scratch/fairoz/JAVA/jdk12/jdk-12-ea+04/bin/java -p modulepath -m bug/bug.ModuleFindDefault Error occurred during initialization of boot layer java.lang.module.FindException: Error reading module: modulepath Caused by: java.lang.module.InvalidModuleDescriptorException: ModuleFindDefault.class found in top-level directory (unnamed package not allowed in module)
07-08-2018

Additional information received from submitter, Steps to reproduce. To trigger the bug, this test needs to be in an named module.** Please add a simple module-info.java, containing the following: module bug { } placing the attached test in a package bug, and compile & run it using the following commands: mkdir modulepath javac -d modulepath module-info.java bug/ModuleFindDefault.java java -p modulepath -m bug/bug.ModuleFindDefault
07-08-2018

Attached program doesn't lead to any exception or errors. Below is the output -sh-4.2$ /scratch/fairoz/JAVA/jdk10.0.2/bin/java ModuleFindDefault java.util.Collections$ReverseComparator2@e842775d Requested submitter to provide the reproducible test case
06-08-2018