Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mandrel cannot dynamically load awt shared libraries from OpenJDK distro #487

Closed
Karm opened this issue Mar 21, 2023 · 33 comments
Closed

Mandrel cannot dynamically load awt shared libraries from OpenJDK distro #487

Karm opened this issue Mar 21, 2023 · 33 comments
Assignees
Labels
affects/JDK17 JDK17 related bug Something isn't working

Comments

@Karm
Copy link
Collaborator

Karm commented Mar 21, 2023

This is a followup on

The relevant change in GraalVM's behavior is: oracle#4921

TL;DR:

  • relevant .so libraries load just fine when Mandrel is built with LabsJDK distro ✔️
  • .so libs cannot be loaded, dlopen returns null pointer, when Mandrel is built with OpenJDK Temurin distro ❌

Steps to reproduce

With this tiny reproducer app:

import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.FontFormatException;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException, FontFormatException {
        final BufferedImage i = new BufferedImage(320, 200, BufferedImage.TYPE_4BYTE_ABGR);
        final Graphics2D g = (Graphics2D) i.getGraphics();
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, 320, 200);
        g.setColor(Color.RED);
        g.fillOval(0, 0, 320, 200);
        g.dispose();
        ImageIO.write(i, "PNG", new File("image.png"));
    }
}

I am unable to make it work at runtime with OpenJDK Temurin based Mandrel. It fails at dlopen (although the file is really there and it seems found and loaded by the native dl).

Steps to reproduce - Temurin OpenJDK ❌

$ export JAVA_HOME=/home/karm/tmp/mandrel-23.0-SNAPSHOT-openjdk/;export GRAALVM_HOME=${JAVA_HOME};export PATH=${JAVA_HOME}/bin:${PATH}
$ native-image --version
native-image 23.0.0-deva81ecbe6def2 Mandrel Distribution (Java Version 17.0.6+10)
$ javac Main.java
$ java -agentlib:native-image-agent=config-output-dir=native-image Main
$ native-image --no-fallback -g -O0 -H:+TrackNodeSourcePosition -H:ConfigurationFileDirectories=native-image Main
...
Produced artifacts:
 /home/karm/workspaceRH/dev-null/awt-circle/libawt.so (jdk_library)
 /home/karm/workspaceRH/dev-null/awt-circle/libawt_headless.so (jdk_library)
 /home/karm/workspaceRH/dev-null/awt-circle/libawt_xawt.so (jdk_library)
 /home/karm/workspaceRH/dev-null/awt-circle/libfontmanager.so (jdk_library)
 /home/karm/workspaceRH/dev-null/awt-circle/libjava.so (jdk_library_shim)
 /home/karm/workspaceRH/dev-null/awt-circle/libjavajpeg.so (jdk_library)
 /home/karm/workspaceRH/dev-null/awt-circle/libjvm.so (jdk_library_shim)
 /home/karm/workspaceRH/dev-null/awt-circle/liblcms.so (jdk_library)
 /home/karm/workspaceRH/dev-null/awt-circle/main (executable)
 /home/karm/workspaceRH/dev-null/awt-circle/main.debug (debug_info)
 /home/karm/workspaceRH/dev-null/awt-circle/sources (debug_info)
==============================================================
Finished generating 'main' in 41.6s.
...
$ LD_DEBUG=all ./main 2>&1 | tee mandrel-openjdk-log.txt

(-g -O0 -H:+TrackNodeSourcePosition is just to use gdb, no impact on reproducibility of the issue)

It fails to load needed .so libs:

9950 Exception in thread "main" java.lang.UnsatisfiedLinkError: no awt in java.library.path
9951   at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryRelative(NativeLibrarySupport.java:136)
9952   at [email protected]/java.lang.ClassLoader.loadLibrary(ClassLoader.java:50)
9953   at [email protected]/java.lang.Runtime.loadLibrary0(Runtime.java:818)
9954   at [email protected]/java.lang.System.loadLibrary(System.java:1989)
9955   at [email protected]/java.awt.image.ColorModel$1.run(ColorModel.java:210)

Full log: mandrel-openjdk-log.txt [910K]

I am using a home built Mandrel, mandrel-23.0-SNAPSHOT.tar.xz [195M],

native-image 23.0.0-deva81ecbe6def2 Mandrel Distribution (Java Version 17.0.6+10)

made of GraalVM a81ecbe with this diff:

diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java
index 358f4f4b649d..b1e1192df8a0 100644
--- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java
+++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixNativeLibraryFeature.java
@@ -185,6 +185,7 @@ final class PosixNativeLibrarySupport extends JNIPlatformNativeLibrarySupport {
             }
             assert dlhandle.isNull();
             dlhandle = PosixUtils.dlopen(canonicalIdentifier, Dlfcn.RTLD_LAZY());
+            System.out.printf("KARM: RTLD_LAZY Status is null: %s of %s.\n", dlhandle.isNull(), canonicalIdentifier);
             return dlhandle.isNonNull();
         }
 
diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java
index c07d6af2f65a..dfd8bd28465b 100644
--- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java
+++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixUtils.java
@@ -220,6 +220,7 @@ public class PosixUtils {
     public static PointerBase dlopen(String file, int mode) {
         try (CCharPointerHolder pathPin = CTypeConversion.toCString(file)) {
             CCharPointer pathPtr = pathPin.get();
+            System.out.printf("KARM: Calling Dlfcn.dlopen(%s,...)\n",file );
             return Dlfcn.dlopen(pathPtr, mode);
         }
     }

Peek into the log

You can see that the native dlopen failed, but not because it wouldn't find the file. It rather failed to load its dependencies' symbols, IMHO.

See the mandrel-openjdk-log.txt [910K] between line

2701 KARM: Calling Dlfcn.dlopen(/home/karm/workspaceRH/dev-null/awt-circle/libawt.so,...)

and line

9919 KARM: RTLD_LAZY Status is null: true of /home/karm/workspaceRH/dev-null/awt-circle/libawt.so.

You can find this:

9910     194208: /home/karm/workspaceRH/dev-null/awt-circle/libawt.so: error: symbol lookup error: undefined symbol: JNU_ThrowInternalError (fatal)

With a gdb gdb-session.txt [3.9K], one can see that it is trying to fine any suitable libawt.so and it might look like the file is just not found. The file is found all right the first time, it just fails to load.

LabsJDK ✔️

Building exactly the same Mandrel distro as mentioned above, this time with LabsJDK 17.0.7+4-jvmci-23.0-b09-linux-amd64 makes it work.

See the full successful log: mandrel-labs-log.txt [4.0M]

Between lines:

 2701 KARM: Calling Dlfcn.dlopen(/home/karm/workspaceRH/dev-null/awt-circle/libawt.so,...)

and

16178 KARM: RTLD_LAZY Status is null: false of /home/karm/workspaceRH/dev-null/awt-circle/libawt.so.

The AWT lib was successfully loaded.

I am not sure at the moment, whether we need a change on the Temurin side, in how it builds those shared objects or whether we could adjust the shim generation on the Mandrel side...

FYI @zakkak @jerboaa

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 21, 2023

Can we disable AWT tests for 23.x for the time being until this is resolved?

@zakkak
Copy link
Collaborator

zakkak commented Mar 22, 2023

I am not sure at the moment, whether we need a change on the Temurin side, in how it builds those shared objects

FWIW I tried copying the so files from the GraalVM build to the Mandrel build and it still fails, so to me it doesn't look like an issue with the so files.

@Karm
Copy link
Collaborator Author

Karm commented Mar 22, 2023

Maybe the shim generation? private void makeShimLibrary(String shimName) { ? in JNIRegistrationSupport.java? i.e. .so from JDk are fine, but the re-exports shim is incompatible?

@zakkak
Copy link
Collaborator

zakkak commented Mar 22, 2023

If I am interpreting the logs correctly JNU_ThrowInternalError is actually found in main (when using GraalVM)

symbol=JNU_ThrowInternalError;  lookup in file=./main [0]
binding file /home/zakkak/code/tmp/awt-test/libawt.so [0] to ./main [0]: normal symbol `JNU_ThrowInternalError'

On the contrary, when using Mandrel if fails to find the symbol in main and thus loading libawt fails:

symbol=JNU_ThrowInternalError;  lookup in file=./main [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libz.so.1 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libc.so.6 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/home/zakkak/code/tmp/awt-test/libawt.so [0]
symbol=JNU_ThrowInternalError;  lookup in file=/home/zakkak/code/tmp/awt-test/libjvm.so [0]
symbol=JNU_ThrowInternalError;  lookup in file=/home/zakkak/code/tmp/awt-test/libjava.so [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libm.so.6 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libdl.so.2 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libc.so.6 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
/home/zakkak/code/tmp/awt-test/libawt.so: error: symbol lookup error: undefined symbol: JNU_ThrowInternalError (fatal)

which makes me think that this is not an issue related to the .so files from the JDK being copied/generated along the image. The reason the symbol doesn't end up in main at build time, however, might be related to them....

Note that the shim generation in Mandrel and GraalVM is responsible for the "generation" (copying actually) of:

  • libawt_headless.so
  • libawt.so
  • libawt_xawt.so
  • libfontmanager.so
  • libjavajpeg.so
  • liblcms.so

Path libraryPath = accessImpl.getImagePath().resolveSibling(library);
Files.copy(jdkLibDir.resolve(library), libraryPath, REPLACE_EXISTING);
BuildArtifacts.singleton().add(ArtifactType.JDK_LIBRARY, libraryPath);
debug.log("%s: OK", library);

While it also generates the dummy/empty:

  • libjava.so
  • libjvm.so

/*
* To satisfy the dynamic loader and enable re-export it is enough to have a library
* with the expected name. So we just create an empty one ...
*/
linkerCommand = ImageSingletons.lookup(CCompilerInvoker.class)
.createCompilerCommand(List.of("-shared", "-x", "c"), shimLibrary, Path.of("/dev/null"));

the actual contents (at least the reachable ones) of which are expected to be statically linked in main (which appears to be what's not happening in Mandrel)

@Karm
Copy link
Collaborator Author

Karm commented Mar 22, 2023

@jerboaa @zakkak
Fun fact:

When I grab LabsJDK jdk-17.0.7+4 and build it, e.g. with

bash ./configure  
    --with-zlib=bundled --with-libjpeg=bundled --with-libpng=bundled --with-lcms=bundled
    --with-giflib=bundled --with-stdc++lib=static --disable-warnings-as-errors --with-boot-jdk=/var/X/JDKs/openjdk-17
    --enable-unlimited-crypto --with-jvm-features=zgc,shenandoahgc
    --with-version-feature=17 --with-version-interim=0 --with-version-update=7 --with-version-patch=4

...and then build Mandrel with it, using Graal's fairly recent master a81ecbe, and then use that to run the reproducer, it fails in the same way as if I built with vanilla JDK.

So it's probably not about what is different in LabsJDK but rather about how it was built.

$ ./main
KARM: Calling Dlfcn.dlopen(/home/karm/workspaceRH/dev-null/awt-circle/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /home/karm/workspaceRH/dev-null/awt-circle/libawt.so.
KARM: Calling Dlfcn.dlopen(/usr/lib64/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /usr/lib64/libawt.so.
KARM: Calling Dlfcn.dlopen(/usr/lib64/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /usr/lib64/libawt.so.
KARM: Calling Dlfcn.dlopen(/usr/lib/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /usr/lib/libawt.so.
KARM: Calling Dlfcn.dlopen(/usr/lib/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /usr/lib/libawt.so.
Exception in thread "main" java.lang.UnsatisfiedLinkError: no awt in java.library.path
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryRelative(NativeLibrarySupport.java:136)
        at [email protected]/java.lang.ClassLoader.loadLibrary(ClassLoader.java:50)
        at [email protected]/java.lang.Runtime.loadLibrary0(Runtime.java:818)
        at [email protected]/java.lang.System.loadLibrary(System.java:1989)
        at [email protected]/java.awt.image.ColorModel$1.run(ColorModel.java:210)
        at [email protected]/java.awt.image.ColorModel$1.run(ColorModel.java:208)
        at [email protected]/java.security.AccessController.executePrivileged(AccessController.java:171)
        at [email protected]/java.security.AccessController.doPrivileged(AccessController.java:318)
        at [email protected]/java.awt.image.ColorModel.loadLibraries(ColorModel.java:207)
        at [email protected]/java.awt.image.ColorModel.<clinit>(ColorModel.java:220)
        at [email protected]/java.awt.image.BufferedImage.<clinit>(BufferedImage.java:286)
        at Main.main(Main.java:16)

$ native-image --version
native-image 23.0.0-deva81ecbe6def2 Mandrel Distribution (Java Version 17.0.7.4-internal+0-adhoc.karm.labs-openjdk-17)

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 22, 2023

If I am interpreting the logs correctly JNU_ThrowInternalError is actually found in main (when using GraalVM)

symbol=JNU_ThrowInternalError;  lookup in file=./main [0]
binding file /home/zakkak/code/tmp/awt-test/libawt.so [0] to ./main [0]: normal symbol `JNU_ThrowInternalError'

On the contrary, when using Mandrel if fails to find the symbol in main and thus loading libawt fails:

symbol=JNU_ThrowInternalError;  lookup in file=./main [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libz.so.1 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libc.so.6 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/home/zakkak/code/tmp/awt-test/libawt.so [0]
symbol=JNU_ThrowInternalError;  lookup in file=/home/zakkak/code/tmp/awt-test/libjvm.so [0]
symbol=JNU_ThrowInternalError;  lookup in file=/home/zakkak/code/tmp/awt-test/libjava.so [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libm.so.6 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libdl.so.2 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/libc.so.6 [0]
symbol=JNU_ThrowInternalError;  lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
/home/zakkak/code/tmp/awt-test/libawt.so: error: symbol lookup error: undefined symbol: JNU_ThrowInternalError (fatal)

which makes me think that this is not an issue related to the .so files from the JDK being copied/generated along the image. The reason the symbol doesn't end up in main at build time, however, might be related to them....

Note that the shim generation in Mandrel and GraalVM is responsible for the "generation" (copying actually) of:

* libawt_headless.so

* libawt.so

* libawt_xawt.so

* libfontmanager.so

* libjavajpeg.so

* liblcms.so

Path libraryPath = accessImpl.getImagePath().resolveSibling(library);
Files.copy(jdkLibDir.resolve(library), libraryPath, REPLACE_EXISTING);
BuildArtifacts.singleton().add(ArtifactType.JDK_LIBRARY, libraryPath);
debug.log("%s: OK", library);

While it also generates the dummy/empty:

* libjava.so

* libjvm.so

/*
* To satisfy the dynamic loader and enable re-export it is enough to have a library
* with the expected name. So we just create an empty one ...
*/
linkerCommand = ImageSingletons.lookup(CCompilerInvoker.class)
.createCompilerCommand(List.of("-shared", "-x", "c"), shimLibrary, Path.of("/dev/null"));

the actual contents (at least the reachable ones) of which are expected to be statically linked in main (which appears to be what's not happening in Mandrel)

Thanks for that. Yes, that matches my understanding. The weird thing is this empty libjava.so and libjvm.so trick.

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 22, 2023

@jerboaa @zakkak Fun fact:

When I grab LabsJDK jdk-17.0.7+4 and build it, e.g. with

bash ./configure  
    --with-zlib=bundled --with-libjpeg=bundled --with-libpng=bundled --with-lcms=bundled
    --with-giflib=bundled --with-stdc++lib=static --disable-warnings-as-errors --with-boot-jdk=/var/X/JDKs/openjdk-17
    --enable-unlimited-crypto --with-jvm-features=zgc,shenandoahgc
    --with-version-feature=17 --with-version-interim=0 --with-version-update=7 --with-version-patch=4

...and then build Mandrel with it, using Graal's fairly recent master a81ecbe, and then use that to run the reproducer, it fails in the same way as if I built with vanilla JDK.

So it's probably not about what is different in LabsJDK but rather about how it was built.

$ ./main
KARM: Calling Dlfcn.dlopen(/home/karm/workspaceRH/dev-null/awt-circle/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /home/karm/workspaceRH/dev-null/awt-circle/libawt.so.
KARM: Calling Dlfcn.dlopen(/usr/lib64/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /usr/lib64/libawt.so.
KARM: Calling Dlfcn.dlopen(/usr/lib64/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /usr/lib64/libawt.so.
KARM: Calling Dlfcn.dlopen(/usr/lib/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /usr/lib/libawt.so.
KARM: Calling Dlfcn.dlopen(/usr/lib/libawt.so,...)
KARM: RTLD_LAZY Status is null: true of /usr/lib/libawt.so.
Exception in thread "main" java.lang.UnsatisfiedLinkError: no awt in java.library.path
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryRelative(NativeLibrarySupport.java:136)
        at [email protected]/java.lang.ClassLoader.loadLibrary(ClassLoader.java:50)
        at [email protected]/java.lang.Runtime.loadLibrary0(Runtime.java:818)
        at [email protected]/java.lang.System.loadLibrary(System.java:1989)
        at [email protected]/java.awt.image.ColorModel$1.run(ColorModel.java:210)
        at [email protected]/java.awt.image.ColorModel$1.run(ColorModel.java:208)
        at [email protected]/java.security.AccessController.executePrivileged(AccessController.java:171)
        at [email protected]/java.security.AccessController.doPrivileged(AccessController.java:318)
        at [email protected]/java.awt.image.ColorModel.loadLibraries(ColorModel.java:207)
        at [email protected]/java.awt.image.ColorModel.<clinit>(ColorModel.java:220)
        at [email protected]/java.awt.image.BufferedImage.<clinit>(BufferedImage.java:286)
        at Main.main(Main.java:16)

$ native-image --version
native-image 23.0.0-deva81ecbe6def2 Mandrel Distribution (Java Version 17.0.7.4-internal+0-adhoc.karm.labs-openjdk-17)

Thanks for verifying this, @Karm.

@Karm
Copy link
Collaborator Author

Karm commented Mar 23, 2023

@jerboaa Can you see anything interesting here?

      - name: 'Configure'
        run: >
          bash configure
          --with-conf-name=${{ inputs.platform }}
          ${{ matrix.flags }}
          --with-version-opt=${GITHUB_ACTOR}-${GITHUB_SHA}
          --with-boot-jdk=${{ steps.bootjdk.outputs.path }}
          --with-jtreg=${{ steps.jtreg.outputs.path }}
          --with-gtest=${{ steps.gtest.outputs.path }}
          --enable-jtreg-failure-handler
          --with-zlib=system
          ${{ inputs.extra-conf-options }}

Source: https://github.com/graalvm/labs-openjdk-17/blob/master/.github/workflows/build-linux.yml
Also no extra confs for Linux amd64 https://github.com/graalvm/labs-openjdk-17/blob/master/.github/workflows/main.yml#L120

Comparing to mine:

bash ./configure
--with-zlib=bundled
--with-libjpeg=bundled
--with-libpng=bundled
--with-lcms=bundled
--with-giflib=bundled
--with-stdc++lib=static
--disable-warnings-as-errors
--with-boot-jdk=/var/X/JDKs/openjdk-17
--enable-unlimited-crypto
--with-jvm-features=zgc,shenandoahgc
--with-version-feature=17
--with-version-interim=0
--with-version-update=7
--with-version-patch=4

I have zlib bundled, they have the system one... Not sure what the make labsjdk goal does though.

EDIT:
I also tied building labsjdk with the labsjdk goal, i.e.:

$ sh configure --with-conf-name=labsjdk --with-version-opt=$JVMCI_VERSION 
$ make CONF_NAME=labsjdk graal-builder-image

And then use the labsjdk image rather than the default one to build Mandrel:

/home/karm/workspaceRH/labs-openjdk-17/build/labsjdk/images/graal-builder-jdk/

No dice.

@Karm
Copy link
Collaborator Author

Karm commented Mar 23, 2023

I wanted to get Mandrel or Graal with libawt with debuginfo, Mandrel cannot build with LabsJDK Debug, so I built with LabsJDK and shamelessly replaced lib directory later, with what I found in LabsJDK debug.

The resulting Mandrel distro is unable to build my Quarkus app, so that's a failure. Yet the reason why is a linker failing on:

/bin/ld: /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libnet.a(DatagramPacket.o):
unable to initialize decompress status for section .debug_info
/home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libnet.a: error adding symbols:
File format not recognized
collect2: error: ld returned 1 exit status

What is more interesting to me is that the whole linker command contains also our infamous JNU_ThrowInternalError, i.e.

-Wl,-u,JNU_ThrowInternalError

in the log:

Linker command executed:
/bin/gcc -z noexecstack -Wl,--gc-sections -Wl,--version-script,/tmp/SVM-16873159568579427386/exported_symbols.list -Wl,-x -o /home/karm/workspaceRH/quarkus-quickstarts/awt-graphics-rest-quickstart/target/awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-native-image-source-jar/awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-runner awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-runner.o /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/svm/clibraries/linux-amd64/liblibchelper.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libnet.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libextnet.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libnio.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libmanagement_ext.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libjava.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libfdlibm.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libzip.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/svm/clibraries/linux-amd64/libjvm.a -Wl,--export-dynamic -v -L/tmp/SVM-16873159568579427386 -L/home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc -L/home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/svm/clibraries/linux-amd64 -lz -lpthread -ldl -lrt -Wl,-u,JNU_CallMethodByName -Wl,-u,JNU_CallStaticMethodByName -Wl,-u,JNU_GetEnv -Wl,-u,JNU_GetStaticFieldByName -Wl,-u,JNU_GetStringPlatformChars -Wl,-u,JNU_IsInstanceOfByName -Wl,-u,JNU_NewObjectByName -Wl,-u,JNU_NewStringPlatform -Wl,-u,JNU_ReleaseStringPlatformChars -Wl,-u,JNU_SetFieldByName -Wl,-u,JNU_ThrowArrayIndexOutOfBoundsException -Wl,-u,JNU_ThrowByName -Wl,-u,JNU_ThrowIllegalArgumentException -Wl,-u,JNU_ThrowInternalError -Wl,-u,JNU_ThrowNullPointerException -Wl,-u,JNU_ThrowOutOfMemoryError -Wl,-u,JNI_CreateJavaVM -Wl,-u,JNI_GetCreatedJavaVMs -Wl,-u,JNI_GetDefaultJavaVMInitArgs -Wl,-u,jio_fprintf -Wl,-u,jio_snprintf -no-pie

Linker command output:
Using built-in specs.
COLLECT_GCC=/bin/gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 8.5.0 20210514 (Red Hat 8.5.0-18) (GCC) 
COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/8/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/
LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/8/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-z' 'noexecstack' '-o' '/home/karm/workspaceRH/quarkus-quickstarts/awt-graphics-rest-quickstart/target/awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-native-image-source-jar/awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-runner' '-v' '-L/tmp/SVM-16873159568579427386' '-L/home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc' '-L/home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/svm/clibraries/linux-amd64' '-no-pie' '-mtune=generic' '-march=x86-64'
 /usr/libexec/gcc/x86_64-redhat-linux/8/collect2 -plugin /usr/libexec/gcc/x86_64-redhat-linux/8/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper -plugin-opt=-fresolution=/tmp/ccm447fo.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o /home/karm/workspaceRH/quarkus-quickstarts/awt-graphics-rest-quickstart/target/awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-native-image-source-jar/awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-runner -z noexecstack /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/8/crtbegin.o -L/tmp/SVM-16873159568579427386 -L/home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc -L/home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/svm/clibraries/linux-amd64 -L/usr/lib/gcc/x86_64-redhat-linux/8 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/8/../../.. --gc-sections --version-script /tmp/SVM-16873159568579427386/exported_symbols.list -x awt-graphics-rest-quickstart-1.0.0-SNAPSHOT-runner.o /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/svm/clibraries/linux-amd64/liblibchelper.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libnet.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libextnet.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libnio.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libmanagement_ext.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libjava.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libfdlibm.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libzip.a /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/svm/clibraries/linux-amd64/libjvm.a --export-dynamic -lz -lpthread -ldl -lrt -u JNU_CallMethodByName -u JNU_CallStaticMethodByName -u JNU_GetEnv -u JNU_GetStaticFieldByName -u JNU_GetStringPlatformChars -u JNU_IsInstanceOfByName -u JNU_NewObjectByName -u JNU_NewStringPlatform -u JNU_ReleaseStringPlatformChars -u JNU_SetFieldByName -u JNU_ThrowArrayIndexOutOfBoundsException -u JNU_ThrowByName -u JNU_ThrowIllegalArgumentException -u JNU_ThrowInternalError -u JNU_ThrowNullPointerException -u JNU_ThrowOutOfMemoryError -u JNI_CreateJavaVM -u JNI_GetCreatedJavaVMs -u JNI_GetDefaultJavaVMInitArgs -u jio_fprintf -u jio_snprintf -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/8/crtend.o /usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crtn.o
/bin/ld: /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libnet.a(DatagramPacket.o): unable to initialize decompress status for section .debug_info
/bin/ld: /home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libnet.a(DatagramPacket.o): unable to initialize decompress status for section .debug_info
/home/karm/tmp/mandrel-23.0-SNAPSHOT-labsjdk/lib/static/linux-amd64/glibc/libnet.a: error adding symbols: File format not recognized
collect2: error: ld returned 1 exit status
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.image.NativeImageViaCC.handleLinkerFailure(NativeImageViaCC.java:205)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.image.NativeImageViaCC.runLinkerCommand(NativeImageViaCC.java:151)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.image.NativeImageViaCC.write(NativeImageViaCC.java:117)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:722)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:537)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:408)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:612)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.start(NativeImageGeneratorRunner.java:134)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:94)


@zakkak
Copy link
Collaborator

zakkak commented Mar 23, 2023

What is more interesting to me is that the whole linker command contains also our infamous JNU_ThrowInternalError, i.e.

-Wl,-u,JNU_ThrowInternalError

That's done here:

getShimExports().map(isWindows() ? "/export:"::concat : "-Wl,-u,"::concat)

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 23, 2023

It's only the static libraries which seem to make a difference. I've stopped the native image build, collected the link command and relevant files so I can do further experiments. The link command is this:

rm -f main
GRAALVM_HOME=/path/to/graalvm/build
/usr/bin/gcc -z noexecstack -Wl,--gc-sections -Wl,--version-script,$(pwd)/exported_symbols.list \
  -Wl,-x -o main main.o \
  $GRAALVM_HOME/lib/svm/clibraries/linux-amd64/liblibchelper.a \
  $GRAALVM_HOME/lib/static/linux-amd64/glibc/libnet.a \
  $GRAALVM_HOME/lib/static/linux-amd64/glibc/libnio.a \
  $GRAALVM_HOME/lib/static/linux-amd64/glibc/libjava.a \
  $GRAALVM_HOME/lib/static/linux-amd64/glibc/libfdlibm.a \
  $GRAALVM_HOME/lib/static/linux-amd64/glibc/libzip.a \
  $GRAALVM_HOME/lib/svm/clibraries/linux-amd64/libjvm.a \
  -Wl,--export-dynamic -v \
  -L$(pwd)/tmp-dir \
  -L$GRAALVM_HOME/lib/static/linux-amd64/glibc \
  -L$GRAALVM_HOME/lib/svm/clibraries/linux-amd64 \
  -ldl -lpthread -lz -lrt \
  -Wl,-u,JNU_CallMethodByName \
  -Wl,-u,JNU_CallStaticMethodByName \
  -Wl,-u,JNU_GetEnv \
  -Wl,-u,JNU_GetStaticFieldByName \
  -Wl,-u,JNU_GetStringPlatformChars \
  -Wl,-u,JNU_IsInstanceOfByName \
  -Wl,-u,JNU_NewObjectByName \
  -Wl,-u,JNU_NewStringPlatform \
  -Wl,-u,JNU_ReleaseStringPlatformChars \
  -Wl,-u,JNU_SetFieldByName \
  -Wl,-u,JNU_ThrowArrayIndexOutOfBoundsException \
  -Wl,-u,JNU_ThrowByName \
  -Wl,-u,JNU_ThrowIllegalArgumentException \
  -Wl,-u,JNU_ThrowInternalError \
  -Wl,-u,JNU_ThrowNullPointerException \
  -Wl,-u,JNU_ThrowOutOfMemoryError \
  -Wl,-u,JNI_CreateJavaVM \
  -Wl,-u,JNI_GetCreatedJavaVMs \
  -Wl,-u,JNI_GetDefaultJavaVMInitArgs \
  -Wl,-u,jio_fprintf \
  -Wl,-u,jio_snprintf

If I point this (GRAALVM_HOME) to static libs from a labsjdk build, the result works. If I point it to static libs from an OpenJDK build (e.g. a self built one, or one from Temurin), then it fails. The result is the same for non-working binaries, JNU* symbols don't get exported in those cases. Thus, when libawt.so tries to look them up it finds them (successful case) or doesn't find them in main (unsuccessful case).

FWIW, the linker version script doesn't seem to matter. I've already tried with this base-case:

$ cat exported_symbols.list 
{
global:
*;};

@zakkak
Copy link
Collaborator

zakkak commented Mar 24, 2023

Experimenting with the above I ended up with the following working command:

/usr/bin/gcc -z noexecstack -Wl,--gc-sections -Wl,--version-script,$(pwd)/exported_symbols.list \
  -Wl,-x -o main main.o \
  $MANDREL_HOME/lib/svm/clibraries/linux-amd64/liblibchelper.a \
  $GRAALVM_HOME/lib/static/linux-amd64/glibc/libnet.a \
  $GRAALVM_HOME/lib/static/linux-amd64/glibc/libnio.a \
  $GRAALVM_HOME/lib/static/linux-amd64/glibc/libjava.a \ 
  $MANDREL_HOME/lib/static/linux-amd64/glibc/libfdlibm.a \
  $GRAALVM_HOME/lib/static/linux-amd64/glibc/libzip.a \
  $MANDREL_HOME/lib/svm/clibraries/linux-amd64/libjvm.a \
  -Wl,--export-dynamic -v \
  -L$(pwd)/tmp-dir \
  -L$MANDREL_HOME/lib/static/linux-amd64/glibc \
  -L$MANDREL_HOME/lib/svm/clibraries/linux-amd64 \
  -ldl -lpthread -lz -lrt \
  -Wl,-u,JNU_CallMethodByName \
  -Wl,-u,JNU_CallStaticMethodByName \
  -Wl,-u,JNU_GetEnv \
  -Wl,-u,JNU_GetStaticFieldByName \
  -Wl,-u,JNU_GetStringPlatformChars \
  -Wl,-u,JNU_IsInstanceOfByName \
  -Wl,-u,JNU_NewObjectByName \
  -Wl,-u,JNU_NewStringPlatform \
  -Wl,-u,JNU_ReleaseStringPlatformChars \
  -Wl,-u,JNU_SetFieldByName \
  -Wl,-u,JNU_ThrowArrayIndexOutOfBoundsException \
  -Wl,-u,JNU_ThrowByName \
  -Wl,-u,JNU_ThrowIllegalArgumentException \
  -Wl,-u,JNU_ThrowInternalError \
  -Wl,-u,JNU_ThrowNullPointerException \
  -Wl,-u,JNU_ThrowOutOfMemoryError \
  -Wl,-u,JNI_CreateJavaVM \
  -Wl,-u,JNI_GetCreatedJavaVMs \
  -Wl,-u,JNI_GetDefaultJavaVMInitArgs \
  -Wl,-u,jio_fprintf \
  -Wl,-u,jio_snprintf

The moment I use either of:

  • lib/static/linux-amd64/glibc/libnet.a
  • lib/static/linux-amd64/glibc/libnio.a
  • lib/static/linux-amd64/glibc/libjava.a
  • lib/static/linux-amd64/glibc/libzip.a

from the Mandrel build it fails.

Inspecting libjava.a I see that the only difference (other than some offsets and sizes) is that some symbols (including JNU_ThrowInternal) are marked as HIDDEN in OpenJDK while they are marked as DEFAULT in LabsJDK.

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 24, 2023

Thanks for this, yes some flag when compiling the OpenJDK static libs seems to cause this. We "just" need to figure out which it is ;-)

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 24, 2023

Inspecting libjava.a I see that the only difference (other than some offsets and sizes) is that some symbols (including JNU_ThrowInternal) are marked as HIDDEN in OpenJDK while they are marked as DEFAULT in LabsJDK.

@zakkak I'm curious, how did you manage to see this? Which tool did you use and how? Thanks!

@zakkak
Copy link
Collaborator

zakkak commented Mar 24, 2023

@zakkak I'm curious, how did you manage to see this? Which tool did you use and how? Thanks!

Redirected the output of readelf -a for each version of the library to a file and then diffed them (in Emacs FWIW).

We "just" need to figure out which it is ;-)

That's proving pretty hard so far, because I can't find the build_labsjdk.py file used for the labsjdk-20 builds. I will probably ping the labsjdk team on instructions on how to reproduce their builds.

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 24, 2023

We "just" need to figure out which it is ;-)

That's proving pretty hard so far, because I can't find the build_labsjdk.py file used for the labsjdk-20 builds. I will probably ping the labsjdk team on instructions on how to reproduce their builds.

It's these switches apparently: -fvisibility=hidden -DJNIEXPORT='__attribute__((visibility("hidden")))' which cause the hidden visibililty.

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 24, 2023

https://bugs.openjdk.org/browse/JDK-8239563 is related, but I need to figure out how to use that infra to produce the desired result.

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 24, 2023

And here it is: graalvm/labs-openjdk-17@f5100f0

@zakkak
Copy link
Collaborator

zakkak commented Mar 24, 2023

And here it is: graalvm/labs-openjdk-17@f5100f0

just did the same for 20 :)

graalvm/labs-openjdk-20@be6b24f

The thing is that @Karm said that when building labsjdk on his own he still sees the failures, which doesn't seem to align with the fact that the change in in the repo :/

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 24, 2023

He used an earlier tag, which doesn't have that change: #487 (comment)

@zakkak
Copy link
Collaborator

zakkak commented Mar 24, 2023

He used an earlier tag, which doesn't have that change: #487 (comment)

Oh I see, he didn't grab a jvmci-* tag so essentially it was a standard OpenJDK build. Thanks!

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 24, 2023

I'll do some verification and then try to bring this upstream.

@zakkak
Copy link
Collaborator

zakkak commented Mar 24, 2023

So apparently we need to change how the static builds we use in Mandrel are being built. While @jerboaa works on achieving this. I experimented with a hacky alternative that allows us to change the visibility of the symbols post-build. This is meant to be a possible work around to get things working until we have a proper fix.

The goal is to unhide the symbols we need (anything listed in the export.list provided by GraalVM/Mandrel to the linker script ). Thanks to this SO post we can achieve this doing the following:

Prerequisite

To do the unhiding we will use a small tool called rebind

git clone https://github.com/BR903/ELFkickers
cd ELFkickers/rebind
make
export PATH=$PATH:$(pwd)/

Patch the libraries

# unarchive the static library
mkdir tmp-dir
cd tmp-dir
ar x /path/to/libjava.a # (might need to apply this to other libs as well)
# for symbol in symbols from export.list;
# do
for f in *.o;
do 
  rebind --visibility default $f $symbol;
done
# done  
ar r /path/to/libjava.a *.o

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 24, 2023

Upstream bug for the visibility change: https://bugs.openjdk.org/browse/JDK-8304871

@jerboaa
Copy link
Collaborator

jerboaa commented Mar 30, 2023

Integrated in mainline. JDK 20 and 17 backports in progress.

Edit: Fix is going to be in OpenJDK 17.0.7. It will not be in 20.0.1 as that ship has sailed. 20.0.2 probably (waiting on approval still).

@jerboaa
Copy link
Collaborator

jerboaa commented Apr 4, 2023

Yep, fix will be in 17.0.7 (April) and 20.0.2 (July).

@jerboaa
Copy link
Collaborator

jerboaa commented Apr 7, 2023

With this mandrel build:

$ native-image --version
native-image 17.0.7-beta 2023-04-18
OpenJDK Runtime Environment Mandrel-23.1.0-dev (build 17.0.7-beta+5-202304062331)
OpenJDK 64-Bit Server VM Mandrel-23.1.0-dev (build 17.0.7-beta+5-202304062331, mixed mode)

The reproducer passes for me. That is, it's solved with any EA build equal or later than 2023-04-06 or 17.0.7+6 and better. We can close this once 23.0 mandrel releases in April.

@Karm
Copy link
Collaborator Author

Karm commented Apr 21, 2023

(Milestone: sorry for the noise, twitchy fingers...)

@github-actions
Copy link

This issue appears to be stale because it has been open 30 days with no activity. This issue will be closed in 7 days unless Stale label is removed, a new comment is made, or not-Stale label is added.

@github-actions github-actions bot added the Stale label May 22, 2023
@zakkak zakkak removed the Stale label May 22, 2023
@zakkak zakkak added this to the Mandrel for JDK 17 / JDK 20 milestone May 22, 2023
@zakkak
Copy link
Collaborator

zakkak commented Jun 8, 2023

We can close this once 23.0 mandrel releases in April.

Since this comment, 23.0 mandrel release date has changed to June.
IIRC in order for the release script to work, we need to have all issues in the 23.0.0.0-Final milestone closed.
AFAIK the JDK 17 builds will have this fixed, but not the JDK 20 builds (which IMO is OK as long as we add a note about it).

Are you OK with closing this?

@Karm
Copy link
Collaborator Author

Karm commented Jun 8, 2023

Hmm. O.K. We can clone JDK 20 specific one?

@zakkak
Copy link
Collaborator

zakkak commented Jun 8, 2023

Yes I believe cloning this and making the clone JDK 20 specific, adding an affects/23.0 label, and assigning it to milestone 23.0.1.0-Final should be the way to go.

@zakkak zakkak added the affects/JDK17 JDK17 related label Jun 8, 2023
@jerboaa
Copy link
Collaborator

jerboaa commented Jun 12, 2023

The fix is in JDK 20. It'll get released in July.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affects/JDK17 JDK17 related bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants