oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.15k stars 1.61k forks source link

native-image-agent ceased to work as expected with AWT/JNI #9300

Closed Karm closed 1 month ago

Karm commented 1 month ago

Native agent used to work for determining necessary JNI access configuration, e.g. when it comes to loading headless AWT for transforming images.

Here is a small program that does that:

git clone https://github.com/Karm/dev-null.git
cd dev-null/imageio

:green_circle: GraalVM CE 22.0.1+8.1

$ export JAVA_HOME=/home/karm/X/JDKs/graalvm-community-openjdk-22.0.1+8.1/;export GRAALVM_HOME=${JAVA_HOME};export PATH=${JAVA_HOME}/bin:${PATH}
$ native-image --version
native-image 22.0.1 2024-04-16
GraalVM Runtime Environment GraalVM CE 22.0.1+8.1 (build 22.0.1+8-jvmci-b01)
Substrate VM GraalVM CE 22.0.1+8.1 (build 22.0.1+8, serial gc)
$ mvn clean package
$ java -Djava.awt.headless=true -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image -jar target/imageio.jar
$ jar uf target/imageio.jar -C src/main/resources/ META-INF
$ native-image -J-Djava.awt.headless=true --no-fallback -jar target/imageio.jar target/imageio
$ ./target/imageio -Djava.awt.headless=true -Djava.home=/tmp/FAKE_JAVA_HOME/

Works, images get generated:

$ ls mytest*
mytest.bmp  mytest.gif  mytest.jpg  mytest.png  mytest_Resized_Grace_M._Hopper.png  mytest.svg  mytest.tiff  mytest_toC.png  mytest_toG.png  mytest_toL.png  mytest_toP.png  mytest_toS.png  mytest.wbmp

Note that the fake JAVA_HOME is an empty directory structure to satisfy code paths that are trying to look for fonts in what it thinks is a JDK folder...

$ find /tmp/FAKE_JAVA_HOME/
/tmp/FAKE_JAVA_HOME/
/tmp/FAKE_JAVA_HOME/conf
/tmp/FAKE_JAVA_HOME/conf/fonts
/tmp/FAKE_JAVA_HOME/lib

Let's backup the config the old agent created:

$ mv src/main/resources/META-INF/native-image ./native-image.old

Now off to the latest dev build:

$ rm -rf mytest* dependency-reduced-pom.xml target/

:red_circle: GraalVM CE 24-dev+5.1

$ export JAVA_HOME=/home/karm/X/JDKs/graalvm-community-openjdk-24+5.1;export GRAALVM_HOME=${JAVA_HOME};export PATH=${JAVA_HOME}/bin:${PATH}
$ native-image --version
native-image 24 2025-03-18
GraalVM Runtime Environment GraalVM CE 24-dev+5.1 (build 24+5-jvmci-b01)
Substrate VM GraalVM CE 24-dev+5.1 (build 24+5, serial gc)
$ mvn clean package
$ java -Djava.awt.headless=true -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image -jar target/imageio.jar
$ jar uf target/imageio.jar -C src/main/resources/ META-INF
$ native-image -J-Djava.awt.headless=true --no-fallback -jar target/imageio.jar target/imageio
$ ./target/imageio -Djava.awt.headless=true -Djava.home=/tmp/FAKE_JAVA_HOME/
Fatal error reported via JNI: Could not allocate library name

That fails. The error here is a weird, unrelated message (I'm gonna patch that reporting in JDK's awt_LoadLibrary.c). The real reason is that no expected C->Java JNI invocations work. EDIT: Patched upstream: https://github.com/openjdk/jdk/pull/20169

Thereachability-metadata.json 's JNI section is wrong. I will try to debug exactly why.

If I ditch it and use the old one:

$ mv src/main/resources/META-INF/native-image ./native-image.new
$ cp ./native-image.old src/main/resources/META-INF/native-image -R
$ jar uf target/imageio.jar -C src/main/resources/ META-INF

And run the build again:

$ native-image -J-Djava.awt.headless=true --no-fallback -jar target/imageio.jar target/imageio

It works and images get generated:

$ ./target/imageio -Djava.awt.headless=true -Djava.home=/tmp/FAKE_JAVA_HOME/

All in all I'd say something changed in the way the native agent works or how it should be used. I will paste more details and debug further.

fniephaus commented 1 month ago

Thanks for raising this! We actually noticed this as well, fixes are already in the making (https://github.com/oracle/graal/pull/9292 and https://github.com/oracle/graal/pull/9305).

vjovanov commented 1 month ago

The fixes have been merged. Can you please verify if it fixes the issue with the next dev build?

Karm commented 1 month ago

@vjovanov I can confirm that it works with the HEAD https://github.com/oracle/graal/commit/71e6492, Mandrel dev build mandrel-java24-linux-amd64-24.2.0-dev71e64925a07.tar.gz.

fniephaus commented 1 month ago

Great, thanks for checking!