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.27k stars 1.63k forks source link

Micronaut native-images generated and run inside Docker with `--install-exit-handlers` stuck at startup #2486

Open ilopmar opened 4 years ago

ilopmar commented 4 years ago

Describe the issue

After adding the option --install-exit-handlers to Micronaut, all the test applications in CI stuck during startup.

Before adding the option I tried it locally (in Linux Mint) and it worked without any problem, but then after merging the change all our CI failed.

Steps to reproduce the issue

This happens when building and executing the generated native-image in a docker container like ruby:2.6 which we use for our tests.

To make it easier to reproduce you can generate the fatjar outside docker and then use it inside the container:

Now start a docker container and make sure you install GraalVM and copy the fatjar generated in the previous step: build/libs/basic-app-0.1-all.jar.

docker run -it --rm -v /home/ivan/.sdkman/candidates/java/20.1.0.r8-grl:/graal_dist -v /tmp/micronaut-basic-app:/app ruby:2.6 bash

Then, inside the container:

export JAVA_HOME=/graal_dist
export PATH=$JAVA_HOME/bin:$PATH
cd app
native-image --no-server --static --no-fallback --class-path build/libs/basic-app-0.1-all.jar
./basic-app
...
...
08:18:38.511 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 159ms. Server Running: http://0dd72f33267f:8080

image

That works as expected and the application starts up.


Now, let's generate the native-image with the --install-exit-handlers flag:

native-image --no-server --static --install-exit-handlers --no-fallback --class-path build/libs/basic-app-0.1-all.jar
./basic-app

image

In this screenshot I'm using GraalMV CE 20.1.0 and I get a core dumped. When I tried with GraalVM compiled from master branch (as our CI does) the application got stucked without showing anything on the console.

Describe GraalVM and your environment:

ilopmar commented 4 years ago

I've just discovered that removing the --static flag make it work again with both 20.1.0 and master branch

olpaw commented 4 years ago

Interesting! Can you do the build again where it results in a segfaulting image but with the extra flag --native-image-info so that I can see what kind of clibrary gets linked in.

olpaw commented 4 years ago

@ilopmar when I build a static image with -H:UseMuslC= with --install-exit-handlers I get a working image. Can you try if using -H:UseMuslC makes your static micronaut image build work fine with --install-exit-handlers?

ilopmar commented 4 years ago

The output using --native-image-info:

root@fc744532335c:/app# native-image --no-server --static --install-exit-handlers --no-fallback --class-path build/libs/basic-app-0.1-all.jar --native-image-info
[basic-app:206]    classlist:   7,313.70 ms,  1.43 GB
[basic-app:206]        (cap):     779.65 ms,  1.43 GB
[basic-app:206]        setup:   2,348.42 ms,  1.43 GB
# Building image for target platform: org.graalvm.nativeimage.Platform$LINUX_AMD64
# Using native toolchain:
#   Name: GNU project C and C++ compiler (gcc)
#   Vendor: linux
#   Version: 8.3.0
#   Target architecture: x86_64
#   Path: /usr/bin/gcc
# Using CLibrary: com.oracle.svm.core.c.libc.GLibc
[basic-app:206]     (clinit):   1,377.18 ms,  3.44 GB
# Static libraries:
#   ../../graal_dist/jre/lib/svm/clibraries/linux-amd64/liblibchelper.a
#   ../../graal_dist/jre/lib/libnet.a
#   ../../graal_dist/jre/lib/svm/clibraries/linux-amd64/libstrictmath.a
#   ../../graal_dist/jre/lib/svm/clibraries/linux-amd64/libffi.a
#   ../../graal_dist/jre/lib/libnio.a
#   ../../graal_dist/jre/lib/libjava.a
#   ../../graal_dist/jre/lib/libsunec.a
#   ../../graal_dist/jre/lib/libzip.a
#   ../../graal_dist/jre/lib/svm/clibraries/linux-amd64/libjvm.a
# Other libraries: stdc++,pthread,dl,z,rt
[basic-app:206]   (typeflow):  28,402.07 ms,  3.44 GB
[basic-app:206]    (objects):  24,122.00 ms,  3.44 GB
[basic-app:206]   (features):   3,397.06 ms,  3.44 GB
[basic-app:206]     analysis:  59,095.88 ms,  3.44 GB
[basic-app:206]     universe:   2,210.02 ms,  3.44 GB
[basic-app:206]      (parse):   9,581.42 ms,  3.44 GB
[basic-app:206]     (inline):  17,193.90 ms,  5.51 GB
[basic-app:206]    (compile):  87,249.11 ms,  6.88 GB
[basic-app:206]      compile: 117,390.89 ms,  6.88 GB
[basic-app:206]        image:   5,762.61 ms,  6.80 GB
[basic-app:206]        write:     969.37 ms,  6.80 GB
[basic-app:206]      [total]: 195,419.98 ms,  6.80 GB

When I add -H:UseMuslC it fails with Error: Missing value for option 'UseMuslC'.

After googling a little bit I've followed the steps in this post https://jamesward.com/2020/05/07/graalvm-native-image-tips-tricks/

But it fails because it seems it doesn't support JDK8:

root@fc744532335c:/app# native-image --no-server --static --install-exit-handlers --no-fallback --class-path build/libs/basic-app-0.1-all.jar --native-image-info -H:UseMuslC=/bundle/                                            
[basic-app:407]    classlist:   8,638.30 ms,  1.69 GB
[basic-app:407]        (cap):      12.33 ms,  1.69 GB
[basic-app:407]        setup:     939.49 ms,  1.69 GB
Error: Your version of the JDK does not support statically linking against musl.
Error: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
Error: Image build request failed with exit status 1

I've tried with JDK11 and GraalVM 20.1.0 CE:

root@363f7bff4447:/app# native-image --no-server --static --install-exit-handlers --no-fallback --class-path build/libs/basic-app-0.1-all.jar --native-image-info -H:UseMuslC=bundle/
[basic-app:47]    classlist:   6,053.88 ms,  0.94 GB
[basic-app:47]        (cap):     757.96 ms,  0.94 GB
[basic-app:47]        setup:   2,987.53 ms,  0.94 GB
# Building image for target platform: org.graalvm.nativeimage.Platform$LINUX_AMD64
# Using native toolchain:
#   Name: GNU project C and C++ compiler (gcc)
#   Vendor: linux
#   Version: 8.3.0
#   Target architecture: x86_64
#   Path: /usr/bin/gcc
# Using CLibrary: com.oracle.svm.core.c.libc.MuslLibc
WARNING GR-10238: VarHandle for static field is currently not fully supported. Static field private static volatile java.lang.System$Logger jdk.internal.event.EventHelper.securityLogger is not properly marked for Unsafe access!
[basic-app:47]     (clinit):   1,622.01 ms,  4.64 GB
# Static libraries:
#   ../graal_dist/lib/svm/clibraries/linux-amd64/liblibchelper.a
#   ../graal_dist/lib/svm/static-libs/musl/libnet.a
#   ../graal_dist/lib/svm/clibraries/linux-amd64/libstrictmath.a
#   ../graal_dist/lib/svm/clibraries/linux-amd64/libffi.a
#   ../graal_dist/lib/svm/static-libs/musl/libextnet.a
#   ../graal_dist/lib/svm/static-libs/musl/libnio.a
#   ../graal_dist/lib/svm/static-libs/musl/libjava.a
#   ../graal_dist/lib/svm/static-libs/musl/libsunec.a
#   ../graal_dist/lib/svm/clibraries/linux-amd64/libjvm.a
#   ../graal_dist/lib/svm/static-libs/musl/libzip.a
# Other libraries: stdc++,pthread,dl,z,rt
[basic-app:47]   (typeflow):  29,929.54 ms,  4.64 GB
[basic-app:47]    (objects):  35,068.99 ms,  4.64 GB
[basic-app:47]   (features):   4,438.57 ms,  4.64 GB
[basic-app:47]     analysis:  73,863.46 ms,  4.64 GB
[basic-app:47]     universe:   2,806.41 ms,  4.64 GB
[basic-app:47]      (parse):   8,073.35 ms,  4.64 GB
[basic-app:47]     (inline):  10,887.65 ms,  6.54 GB
[basic-app:47]    (compile):  48,762.16 ms,  6.27 GB
[basic-app:47]      compile:  71,631.68 ms,  6.36 GB
[basic-app:47]        image:   6,486.55 ms,  6.36 GB
[basic-app:47]        write:   1,015.53 ms,  6.36 GB
[basic-app:47]      [total]: 165,215.13 ms,  6.36 GB

It now works and I'm able to start the native image. The problem with this solution is that we can't use JDK8...

For the moment we are not using static images anymore because of issues like this https://github.com/oracle/graal/issues/571 (that apparently are also fixed using musl.

olpaw commented 4 years ago

It now works and I'm able to start the native image. The problem with this solution is that we can't use JDK8...

@gradinac are there any plans to bring musl support also to Java 8?

olpaw commented 4 years ago

For the moment we are not using static images anymore because of issues like this #571 (that apparently are also fixed using musl.

Yes. That motivated the muslc support that we have now.

The problem with this solution is that we can't use JDK8...

What is holding you back from switching to Java 11 based images?

ilopmar commented 4 years ago

What is holding you back from switching to Java 11 based images?

Micronaut supports a minimum of Java 8, so we can't force users to update to 11. We test all our Micronaut-GraalVM applications with both JDK 8 and 11: https://gitlab.com/micronaut-projects/micronaut-graal-tests/pipelines, so we could need something that works for both.

gradinac commented 4 years ago

As of now, there are no plans to support musl on Java 8 officially. For Java 11, we have leveraged the Portola project to import musl-related changes into the labsjdk-11. We then build the JDK on a musl-based system (Alpine), from which we then fetch the static libraries. I can't think of a viable workaround for this when using the --static flag on Java 8 short of doing something similar as we did for 11.