JDK-8031359 : Invocable.getInterface() works incorrectly if interface has default methods
  • Type: Bug
  • Component: core-libs
  • Sub-Component: javax.script
  • Affected Version: 8u20
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2014-01-02
  • Updated: 2014-07-29
  • Resolved: 2014-01-14
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 8 JDK 9
8u20Fixed 9 b02Fixed
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b121)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b63, mixed mode)

A DESCRIPTION OF THE PROBLEM :
According to the specification, javax.script.Invocable.getInterface() returns null if the script does not implement every method defined in the specified interface. Surprisingly, this is also true for any default methods defined in the interface.

The javadoc of getInterface() does not speak about default methods, but common sense suggests that behavior should resemble that of ordinary Java classes implementing the interface.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
foo
bar
foo 2
default bar
ACTUAL -
foo
bar
[i2 == null -> NPE thrown]

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.script.*;

public class Test {
    public static void main(String[] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
        Invocable invocable = (Invocable) engine;

        Object o1 = engine.eval("({ foo: function() { return 'foo'; }, bar: function() { return 'bar'; } });");
        I i1 = invocable.getInterface(o1, I.class);
        Object o2 = engine.eval("({ foo: function() { return 'foo 2'; } });");
        I i2 = invocable.getInterface(o2, I.class);

        System.out.println(i1.foo());
        System.out.println(i1.bar());
        System.out.println(i2.foo());
        System.out.println(i2.bar());
    }

    public static interface I {
        String foo();

        default String bar() {
            return "default bar";
        }
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Don't use default methods together with Invocable.getInterface().
Comments
Fix pushed to nashorn/jdk9 forest: changeset: 690:d1d4d669373c tag: tip user: sundar date: Thu Jan 09 19:23:34 2014 +0530 summary: 8031359: Invocable.getInterface() works incorrectly if interface has default methods
09-01-2014

Two parts to this bug: 1) NashornScriptEngine checking for implementation for default methods as well. Should skip that. 2) Java adapter bytecode generator should generate interface super calls for default methods (rather than super calls to super class always)
09-01-2014

Yes, bug reproduced as mentioned. Interface's default method implementation is not invoked.
08-01-2014