What JavaScript Engine Does JavaFX WebView Use? OpenJDK vs Oracle JDK Comparison & JSR 223 Usage Guide

JavaFX WebView is a powerful UI component that enables developers to embed web content (HTML, CSS, JavaScript) directly into Java applications. Whether you’re building a desktop app with embedded dashboards, a hybrid mobile app, or a rich client interface, WebView bridges the gap between Java and web technologies. A critical aspect of WebView’s functionality is its JavaScript engine—responsible for executing JavaScript code within the embedded web content.

In this blog, we’ll demystify the JavaScript engine powering JavaFX WebView, compare its behavior across OpenJDK and Oracle JDK distributions, and explore how to integrate JavaScript with Java using JSR 223 (the Scripting for the Java Platform specification). By the end, you’ll have a clear understanding of WebView’s internals, distribution differences, and best practices for scripting integration.

Table of Contents#

  1. What is JavaFX WebView?
    • 1.1 Key Features of WebView
  2. JavaScript Engines in JavaFX WebView: Under the Hood
    • 2.1 WebKit and JavaScriptCore: The Core Components
    • 2.2 How WebView Integrates JavaScriptCore
  3. OpenJDK vs. Oracle JDK: WebView JavaScript Engine Comparison
    • 3.1 Historical Context: JavaFX in JDK
    • 3.2 Modern Distributions: JavaFX as a Separate Module
    • 3.3 JavaScript Engine: Same Core, Different Packaging
    • 3.4 Licensing and Support Considerations
  4. JSR 223: Scripting for Java Integration
    • 4.1 What is JSR 223?
    • 4.2 JSR 223 and JavaScript: From Nashorn to GraalVM
  5. Using JSR 223 with JavaFX WebView: A Practical Guide
    • 5.1 Setting Up JSR 223 with GraalVM JavaScript
    • 5.2 Executing JavaScript via JSR 223
    • 5.3 Interoperability: Java Objects in JSR 223 Scripts
  6. Practical Examples: WebView and JSR 223 in Action
    • 6.1 Example 1: Basic WebView with JavaScript Interaction
    • 6.2 Example 2: JSR 223 with GraalVM JS in JavaFX
  7. Common Pitfalls and Solutions
  8. Conclusion
  9. References

What is JavaFX WebView?#

JavaFX WebView is a lightweight, embeddable web browser component included in the JavaFX framework. Introduced in JavaFX 2.0, it allows developers to render web content (HTML5, CSS3, JavaScript) directly within Java applications. Unlike external browsers, WebView is tightly integrated with JavaFX’s UI toolkit, enabling seamless interaction between Java code and web content.

Key Features of WebView#

  • Full Web Standards Support: Based on the WebKit engine, WebView supports modern web standards like HTML5, CSS3, SVG, and JavaScript ES6+.
  • Java-JavaScript Bridge: Enables bidirectional communication between Java code and JavaScript running in the web content.
  • DOM Access: Java code can manipulate the Document Object Model (DOM) of the loaded web page.
  • Lightweight: Optimized for embedding, with a smaller footprint than standalone browsers.

JavaScript Engines in JavaFX WebView: Under the Hood#

To execute JavaScript, WebView relies on a dedicated JavaScript engine. Understanding this engine is critical for optimizing performance and troubleshooting issues.

WebKit and JavaScriptCore: The Core Components#

JavaFX WebView is built on WebKit, an open-source web rendering engine used by browsers like Safari and older versions of Chrome. WebKit includes its own JavaScript engine: JavaScriptCore (also called “JSC”).

  • WebKit: Handles HTML parsing, CSS styling, and layout rendering.
  • JavaScriptCore: Executes JavaScript code, manages memory (via garbage collection), and supports features like just-in-time (JIT) compilation for performance.

JavaScriptCore is a mature engine, optimized for speed and compliance with ECMAScript standards. It powers JavaScript execution in all WebView instances, regardless of the Java distribution (OpenJDK or Oracle JDK), as we’ll explore later.

How WebView Integrates JavaScriptCore#

When you load a web page in WebView, the following happens:

  1. WebKit parses the HTML/CSS and constructs the DOM.
  2. JavaScriptCore executes any embedded <script> tags or JavaScript called via Java.
  3. The Java-JavaScript bridge (via WebEngine) allows Java code to invoke JavaScript functions and vice versa.

For example, Java can call a JavaScript function in the web page using webEngine.executeScript("myFunction()"), and JavaScript can call Java methods annotated with @JavascriptInterface.

OpenJDK vs. Oracle JDK: WebView JavaScript Engine Comparison#

A common question is whether the JavaScript engine in WebView differs between OpenJDK and Oracle JDK. The answer lies in the history of JavaFX and how it’s distributed today.

Historical Context: JavaFX in JDK#

  • Oracle JDK 8 and Earlier: JavaFX was bundled with Oracle JDK, including WebView and its WebKit/JavaScriptCore dependencies.
  • JDK 11 and Later: Oracle removed JavaFX from the JDK, making it a separate project (OpenJFX). Today, JavaFX is maintained by the OpenJFX community and distributed independently.

Modern Distributions: JavaFX as a Separate Module#

Since JDK 11, both OpenJDK and Oracle JDK do not include JavaFX by default. To use WebView, you must:

  • Add JavaFX as a dependency (e.g., via Maven/Gradle) using the OpenJFX SDK.
  • Use a JDK distribution that bundles JavaFX, such as:
    • BellSoft Liberica JDK
    • Azul ZuluFX
    • SapMachine with JavaFX
    • Oracle JDK (via commercial licenses for older versions, though not recommended for new projects).

JavaScript Engine: Same Core, Different Packaging#

The JavaScript engine (JavaScriptCore) in WebView is identical across OpenJDK and Oracle JDK distributions. This is because:

  • OpenJFX (the open-source JavaFX implementation) uses the same WebKit/JavaScriptCore codebase as the original Oracle-maintained JavaFX.
  • Distributions like Liberica or ZuluFX bundle OpenJFX, ensuring consistency in the underlying engine.

The only differences lie in packaging and support, not the engine itself:

  • OpenJDK-based distributions: Rely on community-driven OpenJFX builds, with support from vendors like BellSoft or Azul.
  • Oracle JDK: Requires a commercial license for JavaFX (if using older versions) and may include proprietary patches, but the core JavaScriptCore engine remains unchanged.

Licensing and Support Considerations#

  • OpenJDK + OpenJFX: Open-source, free to use, and supported by third-party vendors. Ideal for most projects.
  • Oracle JDK + JavaFX: Requires a commercial license (since Oracle JDK 11+), with support from Oracle. Only necessary for enterprise environments with specific Oracle support contracts.

JSR 223: Scripting for Java Integration#

While WebView uses JavaScriptCore for web content, Java also supports general-purpose scripting via JSR 223 (Scripting for the Java Platform). JSR 223 defines a standard API for embedding scripts (JavaScript, Python, Ruby, etc.) in Java applications.

What is JSR 223?#

JSR 223 provides a framework to:

  • Load script engines dynamically.
  • Execute scripts from Java.
  • Share objects between Java and scripts (e.g., passing a Java list to JavaScript).

Key classes include:

  • ScriptEngineManager: Discovers and instantiates script engines.
  • ScriptEngine: Executes scripts and manages script-Java interaction.

JSR 223 and JavaScript: From Nashorn to GraalVM#

Historically, JSR 223 used Oracle’s Nashorn engine for JavaScript. However:

  • Nashorn was deprecated in JDK 11 and removed in JDK 15.
  • Today, the recommended JSR 223 JavaScript engine is GraalVM JavaScript (a high-performance, ECMAScript-compliant engine from Oracle).

Using JSR 223 with JavaFX WebView: A Practical Guide#

JSR 223 and WebView serve different purposes:

  • WebView: Executes JavaScript within a web page context (tied to the DOM).
  • JSR 223: Executes standalone JavaScript (or other scripts) in a Java context (no DOM by default).

However, you can use JSR 223 to enhance WebView workflows, such as pre-processing JavaScript before injecting it into a web page.

Setting Up JSR 223 with GraalVM JavaScript#

To use GraalVM JavaScript with JSR 223:

  1. Add GraalVM JS as a Dependency (Maven example):

    <dependency>  
        <groupId>org.graalvm.js</groupId>  
        <artifactId>js</artifactId>  
        <version>22.3.0</version>  
    </dependency>  
    <dependency>  
        <groupId>org.graalvm.js</groupId>  
        <artifactId>js-scriptengine</artifactId>  
        <version>22.3.0</version>  
    </dependency>  
  2. Initialize the Script Engine:

    import javax.script.ScriptEngine;  
    import javax.script.ScriptEngineManager;  
     
    ScriptEngineManager manager = new ScriptEngineManager();  
    ScriptEngine engine = manager.getEngineByName("graal.js"); // GraalVM JS engine  

Executing JavaScript via JSR 223#

Use engine.eval() to run JavaScript code:

try {  
    // Execute a simple script  
    engine.eval("print('Hello from GraalVM JS!')");  
 
    // Evaluate an expression and get the result  
    Object result = engine.eval("2 + 2");  
    System.out.println("Result: " + result); // Output: 4  
} catch (Exception e) {  
    e.printStackTrace();  
}  

Interoperability: Java Objects in JSR 223 Scripts#

JSR 223 allows scripts to access Java objects. For example:

import java.util.ArrayList;  
 
// Pass a Java list to JavaScript  
ArrayList<String> list = new ArrayList<>();  
list.add("Java");  
list.add("JavaScript");  
engine.put("myList", list); // Expose list to JS as 'myList'  
 
// Modify the list in JS  
engine.eval("myList.add('GraalVM')");  
 
System.out.println(list); // Output: [Java, JavaScript, GraalVM]  

Practical Examples: WebView and JSR 223 in Action#

Example 1: Basic WebView with JavaScript Interaction#

This example loads an HTML page in WebView and calls a JavaScript function from Java.

Step 1: Create an HTML File (src/main/resources/page.html)

<!DOCTYPE html>  
<html>  
<body>  
    <h1>WebView Demo</h1>  
    <script>  
        function greet(name) {  
            return "Hello, " + name + "!";  
        }  
    </script>  
</body>  
</html>  

Step 2: JavaFX Application with WebView

import javafx.application.Application;  
import javafx.scene.Scene;  
import javafx.scene.web.WebEngine;  
import javafx.scene.web.WebView;  
import javafx.stage.Stage;  
 
public class WebViewDemo extends Application {  
    @Override  
    public void start(Stage stage) {  
        WebView webView = new WebView();  
        WebEngine webEngine = webView.getEngine();  
 
        // Load the HTML page  
        webEngine.load(getClass().getResource("/page.html").toExternalForm());  
 
        // Wait for the page to load, then call JavaScript  
        webEngine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {  
            if (newState == javafx.concurrent.Worker.State.SUCCEEDED) {  
                // Call JavaScript function 'greet' with argument "JavaFX"  
                Object result = webEngine.executeScript("greet('JavaFX')");  
                System.out.println(result); // Output: Hello, JavaFX!  
            }  
        });  
 
        stage.setScene(new Scene(webView, 800, 600));  
        stage.show();  
    }  
 
    public static void main(String[] args) {  
        launch(args);  
    }  
}  

Example 2: JSR 223 with GraalVM JS in JavaFX#

This example uses JSR 223 to pre-process data, then injects the result into WebView.

Step 1: Add GraalVM JS Dependencies (as shown earlier).

Step 2: JavaFX App with JSR 223 Integration

import javafx.application.Application;  
import javafx.application.Platform;  
import javafx.scene.Scene;  
import javafx.scene.web.WebEngine;  
import javafx.scene.web.WebView;  
import javafx.stage.Stage;  
import javax.script.ScriptEngine;  
import javax.script.ScriptEngineManager;  
 
public class JSR223WebViewDemo extends Application {  
    @Override  
    public void start(Stage stage) {  
        WebView webView = new WebView();  
        WebEngine webEngine = webView.getEngine();  
        webEngine.loadContent("<h1>JSR 223 + WebView</h1><div id='output'></div>");  
 
        // Initialize JSR 223 GraalVM JS engine  
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("graal.js");  
 
        try {  
            // Use JSR 223 to process data  
            engine.put("name", "GraalVM");  
            String jsCode = "`Processed: Hello, ${name}!`";  
            String processedText = (String) engine.eval(jsCode);  
 
            // Inject processed text into WebView's DOM (run on UI thread)  
            Platform.runLater(() -> {  
                webEngine.executeScript("document.getElementById('output').textContent = '" + processedText + "'");  
            });  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
 
        stage.setScene(new Scene(webView, 800, 600));  
        stage.show();  
    }  
 
    public static void main(String[] args) {  
        launch(args);  
    }  
}  

Common Pitfalls and Solutions#

1. Confusing WebView’s JavaScriptCore with JSR 223 Engines#

  • Issue: Assuming WebView uses the same JS engine as JSR 223 (e.g., GraalVM JS). They are separate!
  • Solution: Use WebView’s WebEngine for web page JS and JSR 223 for standalone scripting.

2. Threading and UI Updates#

  • Issue: JavaScript in WebView runs on a background thread. Updating the JavaFX UI from JS requires Platform.runLater().
  • Solution: Wrap UI updates in Platform.runLater() to ensure they execute on the JavaFX Application Thread.

3. Handling Deprecated Nashorn Engine#

  • Issue: Using manager.getEngineByName("nashorn") throws errors in JDK 15+.
  • Solution: Migrate to GraalVM JS and use graal.js as the engine name.

Conclusion#

JavaFX WebView relies on the WebKit engine’s JavaScriptCore to execute JavaScript, ensuring consistent performance and standards compliance across OpenJDK and Oracle JDK distributions. While the core engine is identical, distribution and licensing differ—OpenJDK-based distributions with bundled OpenJFX (e.g., Liberica, ZuluFX) are recommended for most users.

JSR 223 (via GraalVM JS) complements WebView by enabling standalone JavaScript execution in Java, though it’s important to distinguish between WebView’s web-focused JS engine and JSR 223’s general scripting framework.

By combining WebView for embedded web content and JSR 223 for dynamic scripting, developers can build powerful, hybrid Java applications that leverage the best of both worlds.

References#