Optimistic Typing in Nashorn

I have a bunch of programs written in JavaScript for Nashorn, the fast JavaScript engine shipped with JDK 8 and later. Since I had been working on a NodeJS project for the last couple of months, I hadn't used these programs in the last month or so.

Today I was running a simple program to do some automatic changes on a big HTML file, when I encountered a java.lang.invoke.WrongMethodTypeException error. The error was triggered by a part of the program that was trying to copy a string into the clipboard.

Here is a sample program to explore this issue:

    (function () {
        try {
            var cb = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
            var textPlain = "Hello world!";
            var textHtml = "

" + textPlain + ""; var items = [{ data: textPlain, dataFlavor: new java.awt.datatransfer.DataFlavor("text/plain;class=java.lang.String"), }, { data: textHtml, dataFlavor: new java.awt.datatransfer.DataFlavor("text/html;class=java.lang.String"), }, ]; let owner = new java.awt.datatransfer.ClipboardOwner({ lostOwnership: function (clipboard, contents) { print("OK. Lost ownership..."); }, }); let contents = new java.awt.datatransfer.Transferable({ getTransferData: function (dataFlavor) { var item; items.some(function (itm) { if (itm.dataFlavor.equals(dataFlavor)) { item = itm; return true; } }); if (!item) { throw new java.awt.datatransfer.UnsupportedFlavorException(dataFlavor); } return item.data; }, getTransferDataFlavors: function () { return items.map(function (item) { return item.dataFlavor; }); }, isDataFlavorSupported: function (dataFlavor) { return items.some(function (item) { return item.dataFlavor.equals(dataFlavor); }); } }); cb.setContents(contents, owner); } catch (e) { print(e); } })();

This program tries to copy a string (in text/plain and text/html flavors) into the clipboard.

The program (assuming it is saved in a file called program.js) should be run with a command like this:

    java jdk.nashorn.tools.Shell --language=es6 program.js --

This program would have executed perfectly a few months ago, but since I recently updated my Java instance to version 9.0.1 (and now to 9.0.4), it produces the following error:

    java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(ScriptFunction,Object)int to (ScriptFunction,Object)DataFlavor[]

I have not included the stack trace here, but the problem seems to be in the getTransferDataFlavors method. The method should return DataFlavor[] but Nashorn thinks it returns int.

I looked around in Google and found this thread from Dec. 2017 on nashorn-dev mailing list that mentioned a similar problem.

It turns out the problem has started because of Optimistic Typing in Nashorn, which has been implemented to boost execution speed in Nashorn. Apparently, Nashorn makes assumptions about specific types in methods. In this case, the engine assumes that a method returns int, while in fact it should return DataFlavor[].

For the time being, (as advised in the above-mentioned thread) I could work around this problem by turning off optimistic typing. Here is the command:

    java -Dnashorn.args=-ot=false jdk.nashorn.tools.Shell --language=es6 program.js --

With this flag (-Dnashorn.args=-ot=false), the program runs perfectly and the strings are copied into the clipboard.

There are various ways for implementing Java interfaces in Nashorn code. I tried all of them (using JavaAdapter which was actually introduced in Rhino and is also offered for Nashorn and also using Java.extend). In all cases, however, this error was thrown. It appears that if we want to use optimistic typing in Nashorn, we may need a new mechanism for specifying the method signature (including the return type) when implementing interfaces. I am not aware of any methods to do this for the time being so I am sticking with the turned-off flag. I will have to explore more resources to find out more about this bug.

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now
Logo
Center