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:
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:
@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-imageon 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.