Monday Apr 08, 2013

Keynoting at JAX2013

I have the honor to be keynoting JAX 2013 on April 25. The Keynote is called "Project Nashorn - and why dynamic languages on the JVM really matter". Exciting enough, surely, but it's not just "dynamic languages on the JVM", as it says in the title, that are becoming more and more important - I will show that it's really "languages on the JVM" that matters too, the JVM has its future as a polyglot runtime regardless of paradigm. Also, we are going to look at Project Nashorn as one good example of the future of the JVM.

There will also be a deep dive session about Nashorn during the conference, currently scheduled later the same day.

 The abstract is "More languages than Java have been implemented on top of the JVM since the very beginning in 1995. The platform independent bytecode format has always made it possible to compile anything and have it run on the JVM with the same write once/run anywhere benefits. Lately we are seeing an explosion in JVM languages. This is partly because of Java 7, which is the first giant leap in turning the JVM from a Java runtime to a true dynamic polyglot runtime. This keynote explains why language implementations, especially dynamic languages, are more feasible to implement on top of the JVM than ever and how the JVM can execute them with high performance. As an example, we will go into detail of the Nashorn project, Oracle's new JavaScript runtime, part of the JDK as of Java 8."

I'll see you there, and hopefully the spring weather in in Rhineland-Palatinate beats the spring weather in Stockholm. Probably not much of a competition, really.

Regards, Marcus 

Saturday Apr 06, 2013

To Shell Or Not To Shell

I find myself facing a dilemma today. How should I use Java FX from Nashorn? So far, I have two approaches I could use, but each comes with some issues. Some background first.

Java FX, even though ships with the JDK, is on a different build cycle and has dependencies on elements of the JDK. This arraignment limits Nashorn, which is part of the JDK, from actually having dependencies into Java FX. But, there is a dependency requirement to implement a Java FX application. Java FX applications begin with a subclass instance of javafx.application.Application. Therefore, whatever choice is made, it has to be independent of the JDK (at some point should be part of Java FX.)

The first approach, in general terms, is the easiest to use. It involves using a predefined shell that is similar to jjs but handles the overrides of Application methods init, start and finish. The source of this shell is currently checked into the Nashorn repo under nashorn/tools/fxshell.

 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit if you need additional information or have any
 * questions.
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.stage.Stage;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 * This shell is designed to launch a JavaFX application written in Nashorn JavaScript.
public class FXShell extends Application {
     * Script engine manager to search.
    private ScriptEngineManager manager;
     * Nashorn script engine factory.
    private NashornScriptEngineFactory factory;
     * Main instance of Nashorn script engine.
    private ScriptEngine engine;
     * Needed so that the FX launcher can create an instance of this class.
    public FXShell() {
     * Main entry point. Never actually used.
     * @param args Command line arguments.
    public static void main(String[] args) {
     * Application overrides.
    public void init() throws Exception {
        // Script engine manager to search.
        this.manager = new ScriptEngineManager();
        // Locate the Nashorn script engine factory.  Needed for passing arguments.
        for (ScriptEngineFactory engineFactory : this.manager.getEngineFactories()) {
             if (engineFactory.getEngineName().equals("Oracle Nashorn") &&
                 engineFactory instanceof NashornScriptEngineFactory) {
                this.factory = (NashornScriptEngineFactory)engineFactory;
        // If none located.
        if (this.factory == null) {
            System.err.println("Nashorn script engine not available");
        // Get the command line and JNLP parameters.
        final Parameters parameters = getParameters();
        // To collect the script paths and command line arguments.
        final List<String> paths = new ArrayList<>();
        final List<String> args = new ArrayList<>();
        // Pull out relevant JNLP named parameters.
        final Map<String, String> named = parameters.getNamed();
        for (Map.Entry<String, String> entry : named.entrySet()) {
            final String key = entry.getKey();
            final String value = entry.getValue();
            if ((key.equals("cp") || key.equals("classpath")) && value != null) {
            } else if (key.equals("source") && value != null &&
                       value.toLowerCase().endsWith(".js")) {
        // Pull out relevant command line arguments.
        boolean addNextArg = false;
        boolean addAllArgs = false;
        for (String parameter : parameters.getUnnamed()) {
            if (addAllArgs || addNextArg) {
                addNextArg = false;
            } else if (parameter.equals("--")) {
                addAllArgs = true;
            } else if (parameter.startsWith("-")) {
                addNextArg = parameter.equals("-cp") || parameter.equals("-classpath");
            } else if (parameter.toLowerCase().endsWith(".js")) {
        // Create a Nashorn script engine with specified arguments.
        engine = factory.getScriptEngine(args.toArray(new String[args.size()]));
        // Load initial scripts.
        for (String path : paths) {
        // Invoke users JavaScript init function if present.
        try {
            ((Invocable) engine).invokeFunction("init");
        } catch (NoSuchMethodException ex) {
            // Presence of init is optional.
    public void start(Stage stage) throws Exception {
        // Invoke users JavaScript start function if present.
        try {
            ((Invocable) engine).invokeFunction("start", stage);
        } catch (NoSuchMethodException ex) {
            // Presence of start is optional.
    public void stop() throws Exception {
        // Invoke users JavaScript stop function if present.
        try {
            ((Invocable) engine).invokeFunction("stop");
        } catch (NoSuchMethodException ex) {
            // Presence of stop is optional.
     * Load and evaluate the specified JavaScript file.
     * @param path Path to UTF-8 encoded JavaScript file.
     * @return Last evaluation result (discarded.)
    private Object load(String path) {
        try {
            FileInputStream file = new FileInputStream(path);
            InputStreamReader input = new InputStreamReader(file, "UTF-8");
            return engine.eval(input);
        } catch (FileNotFoundException | UnsupportedEncodingException | ScriptException ex) {
        return null;

To built it you can (cd make ; ant build-fxshell) from within the nashorn repo. The result is in nashorn/dist/nashornfx.jar. To use just java -cp dist/nashornfx.jar <myscript.js> … . For the JDK savvy you can create a launcher by modelling an entry in jdk/makefiles/CompileLaunchers.gmk after the jjs entry.

The big plus for this approach is that it handles almost everything for you. You just have to define a start method with a few class declarations and that is it. The down side is that ideally you would want this implemented as a jjsfx launcher embedded in the JDK. But then we run into the chicken and egg dependency on Java FX.

The second approach only relies on jjs. With a recent modification to Java.extend (currently only in the nashorn forest), it is now possible to subclass javafx.application.Application. and thus launch from within a script. This sounds like all pluses except for the fact you have to wrap your brain around the fact that FX applications take control of execution and has static init dependencies that require careful use in your program.

I prototyped a simple fxinit.js include that shows how we could implement such a scheme. Ignore the implementation quirks. It's simpler than it seems.

GLOBAL = this;
javafx = Packages.javafx;
(Java.extend(javafx.application.Application, {
    init: function() {
        // FX packages and classes must be defined here because they may not be
        // viable until launch time.
        Stage          = javafx.stage.Stage;
        scene          = javafx.scene;
        Scene          = scene.Scene;
        Group          = scene.Group;
        chart          = scene.chart;
        control        = scene.control;
        Button         = control.Button;
        StackPane      = scene.layout.StackPane;
        FXCollections  = javafx.collections.FXCollections;
        ObservableList = javafx.collections.ObservableList;
        Chart          = chart.Chart;
        CategoryAxis   = chart.CategoryAxis;
        NumberAxis     = chart.NumberAxis;
        BarChart       = chart.BarChart;
        XYChart        = chart.XYChart;
        Series         = chart.XYChart$Series;
        Data           = chart.XYChart$Data;
        TreeView       = control.TreeView;
        TreeItem       = control.TreeItem;
        if (GLOBAL.init) {
    start: function(stage) {
        if (GLOBAL.start) {
    stop: function() {
        if (GLOBAL.stop) {
})).class, new (Java.type("java.lang.String[]"))(0));

How you would use it is straight forward. Here is the FX example written for Nashorn;

function start(stage) {
    stage.title = "Hello World!";
    var button = new Button();
    button.text = "Say 'Hello World'";
    button.onAction = function() print("Hello World!");
    var root = new StackPane();
    stage.scene = new Scene(root, 300, 250);;
Note the placement of the load("fxinit.js");. Since this is where the FX Application takes control, anything after the load will not complete until the application exits.

One other quirk. Since you can not static init some of Java FX classes until after the application launches. You can not globally (script level) declare any uses of these classes. Uses can be embedded in methods used after the launch, but no where else. This is a style cramp for me.

There is a third approach I have been considering. It involves some argument trickery, but may play out as a better way of doing things. Imagine jjs fxinit.js -- myscript.js -- my scripts args . The -- indicates the beginning of arguments passed to the script. The notion here is that fxinit.js launches the application and then evals myscript.js. This cleanses my script of any quirks, while putting the onus on getting the command line right.



Technical discussions and status of the Nashorn JavaScript Project.


« April 2013 »