I just tried building a native-image binary with --static --libc=musl see https://www.graalvm.org/latest/reference-manual/native-image/guides/build-static-executables/
and it all worked except I get a stack overflow on one of my tests:
Exception in thread "main" java.lang.StackOverflowError
at org.graalvm.nativeimage.builder/com.oracle.svm.core.graal.snippets.StackOverflowCheckImpl.newStackOverflowError0(StackOverflowCheckImpl.java:360)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.graal.snippets.StackOverflowCheckImpl.newStackOverflowError(StackOverflowCheckImpl.java:356)
at org.graalvm.nativeimage.builder/com.oracle.svm.core.graal.snippets.StackOverflowCheckImpl.throwNewStackOverflowError(StackOverflowCheckImpl.java:336)
at java.base@23.0.1/java.util.regex.Pattern$BmpCharProperty.match(Pattern.java:4133)
at java.base@23.0.1/java.util.regex.Pattern$Branch.match(Pattern.java:4914)
at java.base@23.0.1/java.util.regex.Pattern$GroupHead.match(Pattern.java:4969)
at java.base@23.0.1/java.util.regex.Pattern$Pos.match(Pattern.java:5348)
at java.base@23.0.1/java.util.regex.Pattern$LazyLoop.match(Pattern.java:5142)
at java.base@23.0.1/java.util.regex.Pattern$GroupTail.match(Pattern.java:5000)
at java.base@23.0.1/java.util.regex.Pattern$BranchConn.match(Pattern.java:4878)
at java.base@23.0.1/java.util.regex.Pattern$CharProperty.match(Pattern.java:4110)
at java.base@23.0.1/java.util.regex.Pattern$Branch.match(Pattern.java:4914)
at java.base@23.0.1/java.util.regex.Pattern$GroupHead.match(Pattern.java:4969)
at java.base@23.0.1/java.util.regex.Pattern$LazyLoop.match(Pattern.java:5146)
at java.base@23.0.1/java.util.regex.Pattern$GroupTail.match(Pattern.java:5000)
at java.base@23.0.1/java.util.regex.Pattern$BranchConn.match(Pattern.java:4878)
at java.base@23.0.1/java.util.regex.Pattern$CharProperty.match(Pattern.java:4110)
at java.base@23.0.1/java.util.regex.Pattern$Branch.match(Pattern.java:4914)
at java.base@23.0.1/java.util.regex.Pattern$GroupHead.match(Pattern.java:4969)
at java.base@23.0.1/java.util.regex.Pattern$LazyLoop.match(Pattern.java:5146)
I've never seen this running code in jvm or graalvm compiled before.
It's caused involving a string that at length 322 works but 323 errors.
Obviously involving a regex.
I think it will be hard to track down, so asking here first if anyone has ideas of what might be happening.possibly related: <https://rules.sonarsource.com/java/tag/regex/RSPEC-5998/>
Interesting and thanks. I don't get how statically linking musl would change the stack size though. Any thoughts there?
heh, here's a possible answer from (a 3 years younger) @borkdude! https://github.com/oracle/graal/issues/3398
@highpressurecarsalesm how did you find https://rules.sonarsource.com/java/tag/regex/RSPEC-5998/ btw?
googled "java stackoverflow regex"
I need to learn about this google thing!
I'll try to make an adaptation of https://github.com/babashka/babashka/blob/master/src/babashka/main.clj#L1232-L1267
I got it working. Thank you again @highpressurecarsalesm for finding the right path for me to pursue.
@borkdude I believe that you no longer need this code
https://github.com/babashka/babashka/blob/master/src/babashka/main.clj#L1232-L1250
I believe that -H:CCompilerOption=-Wl,-z,stack-size=2097152 now applies to the main thread as well.
Perhaps that's what wirthi meant in https://github.com/oracle/graal/issues/3398#issuecomment-1907980571
Unrelated to the problem above, here is something that is very interesting...
The --static binary startup time is nearly twice as fast as the binary that dynamically loads libc
$ time ./bin/ys -e1
real 0m0.011s
user 0m0.005s
sys 0m0.007s
vs
$ time ys -e1
real 0m0.020s
user 0m0.005s
sys 0m0.015s
(the ys binary is using SCI, similar to bb)
Also I noticed that the static binary is 53MB and the non-static one is 68MB.
$ ls -lh bin/ys-0.1.80
-rwxr-xr-x 1 ingy ingy 53M Oct 20 16:36 bin/ys-0.1.80*
$ ls -lh ~/.local/bin/ys-0.1.80
-rwxr-xr-x 1 ingy ingy 68M Oct 20 11:24 /home/ingy/.local/bin/ys-0.1.80*
that doesn't make sense to me.Also interesting, I build a native shared library in addition to the native binary executable. I assumed I could static link musl there but that's not the case. See https://github.com/oracle/graal/issues/3053 There are some interesting workarounds in that thread. Something for another day...
Well, dynamically linking probably add some startup time. The file size difference is surprising, but maybe the dynamic linking machinery takes more space than the small amount of things you have to statically link against?
> Well, dynamically linking probably add some startup time. Certainly agree. > The file size difference is surprising, but maybe the dynamic linking machinery takes more space than the small amount of things you have to statically link against? I don't think that's it. 15MB is a lot. Earlier this year @borkdude helped me reduce the binary size a bunch with some tricks he did for babashka. See https://github.com/babashka/babashka/tree/master/src/aaaa_this_has_to_be_first. A few months later my binary size grew unexpectedly (by 15MB I just checked). It's been on my list to investigate but hasn't been important enough for me to do it yet. I'm (totally) guessing that this did something to reverse that.