Contents

Native Image

This guide describes how to build JxBrowser applications as GraalVM native images, what JxBrowser-specific dependency to add, and what you still need to configure in your own application.

JxBrowser supports GraalVM Native Image through the jxbrowser-native-image artifact.

The jxbrowser-native-image artifact supplies the reachability metadata required by JxBrowser itself. In other words, you do not need to prepare reflection or JNI configuration for JxBrowser internals manually.

The reachability metadata is provided in the unified reachability-metadata.json format introduced in GraalVM 23.

Adding the reachability data 

If you use the JxBrowser Gradle plugin, add jxbrowser-native-image to the same module where you declare the regular JxBrowser dependencies:

Gradle
Maven
dependencies {
    implementation(jxbrowser.currentPlatform)
    implementation(jxbrowser.swing)
    implementation(jxbrowser.nativeImage)
}
<dependencies>
    ...
    <dependency>
        <groupId>com.teamdev.jxbrowser</groupId>
        <artifactId>jxbrowser-native-image</artifactId>
        <version>9.0.0</version>
    </dependency>
</dependencies>

If you do not use the JxBrowser Gradle plugin, add com.teamdev.jxbrowser:jxbrowser-native-image:9.0.0 manually and keep its version in sync with the rest of your JxBrowser artifacts.

If your application uses JavaFX, SWT, or Compose Desktop, keep the corresponding UI toolkit dependency as well. The GraalVM artifact does not replace the regular JxBrowser modules. It complements them.

For Swing and JavaFX desktop applications, use a GraalVM distribution that supports desktop native-image builds out of the box. We test JxBrowser with Liberica Native Image Kit (NIK).

JavaScript-accessible types 

If your application exposes Java or Kotlin objects to JavaScript, JxBrowser uses reflection to access them at runtime. Because of this, native-image builds need one extra step to make JavaScript-accessible types work.

In a regular application, it is enough to mark members with @JsAccessible or to make types accessible through JsAccessibleTypes.

In a native image, the same application-specific types must also be registered in your application’s own reachability-metadata.json file:

Java
Kotlin
@JsAccessible
public final class Bridge {
    public String sayHello(String name) {
        return "Hello " + name + "!";
    }
}

public final class App {
    public static void main(String[] args) {
        var engine = Engine.newInstance(HARDWARE_ACCELERATED);
        var browser = engine.newBrowser();
        browser.set(InjectJsCallback.class, params -> {
            var window = params.frame().executeJavaScript("window");
            window.putProperty("bridge", new Bridge());
            return InjectJsCallback.Response.proceed();
        });
    }
}
class Bridge {
    @JsAccessible
    fun sayHello(name: String) = "Hello $name!"
}

fun main() {
    val engine = Engine.newInstance(HARDWARE_ACCELERATED)
    val browser = engine.newBrowser()
    browser.register(InjectJsCallback { params ->
        val window = params.frame().executeJavaScript<JsObject>("window")
        window?.putProperty("bridge", Bridge())
        InjectJsCallback.Response.proceed()
    })
}

Add the bridge type to your application’s reachability-metadata.json file:

{
  "reflection": [
    {
      "type": "com.example.Bridge",
      "methods": [
        {
          "name": "sayHello",
          "parameterTypes": ["java.lang.String"]
        }
      ]
    }
  ]
}

Register every application or third-party type that you expose to JavaScript. If you make Map or Set accessible through JsAccessibleTypes, add matching entries for java.util.Map and java.util.Set as well.

If you expose an interface to JavaScript and then pass a concrete implementation, register both the accessible interface and the implementation class that you inject at runtime.

For more details on @JsAccessible, JsAccessibleTypes, and JavaScript bridge behavior, see the JavaScript guide.

Building the native image 

Once jxbrowser-native-image is on the classpath and your application metadata is in place, build the executable with your usual native-image workflow.

JxBrowser-specific work is limited to:

  • keeping jxbrowser-native-image on the classpath during the native-image build;
  • keeping all JxBrowser artifacts on the same version;
  • adding your own reachability metadata for JavaScript-accessible types from your application.

If your project already uses the GraalVM Native Build Tools plugin, you do not need a separate JxBrowser plugin for native-image support. The extra JxBrowser artifact and your application metadata are enough.