Fork me on GitHub
#graalvm
<
2023-05-13
>
agorgl20:05:33

Hello! I was compiling basic clojure programs to native binaries with by adding clj-easy/graal-build-time dependency and using the following command:

command [(str (io/file graal-home "bin" "native-image"))
           "-jar" jar
           binary
           "-H:+ReportExceptionStackTraces"
           "-J-Dclojure.compiler.direct-linking=true"
           "-J-Dclojure.spec.skip-macros=true"
           "--no-fallback"
           "--static"
           "--verbose"]]
After using the .isFile method from java.io.File I now get this:
Exception in thread "main" java.lang.IllegalArgumentException: No matching field found: isFile for class java.io.File
	at clojure.lang.Reflector.getInstanceField(Reflector.java:397)
	at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:440)
Any idea how to solve this?

borkdude20:05:05

Yes, by adding:

(set! *warn-on-reflection* true) 
to your clojure file and then fixing the reflection warning

agorgl20:05:42

I just found out that a type hint ^java.io.File in my anonymous function that uses the .isFile method solves that!

đź‘Ť 2
agorgl20:05:40

I noticed that when my clojure program uses https://clojuredocs.org/clojure.java.shell/sh then the native graalvm binary hangs on exit, anybody else stumbled into that? (On non-graalvm builds/runs it does not hang, and also the child process called by sh prints something and exits immediately in both normal and graalvm builds as expected)

borkdude20:05:55

Use (shutdown-agents) at the end of your -main function

agorgl20:05:45

Damn you saved me once more, thanks!

agorgl20:05:54

Any explanation why this happens on graalvm builds?

borkdude20:05:00

I don't recall the exact reason, but this is standard practice in Clojure CLI tools

agorgl20:05:13

Thanks again

markus07:06:24

The reason for needing it in general is that the pool threads are not “daemon” threads and must be waited for before the process can exit so the thread pool has to be explicitly shut down to prevent the waiting, which never ends because the threads are sleeping in a loop expecting new jobs to be submitted. Why it is only a problem with Graal is strange. It should be the same always because the requirement to join threads is an OS thing, not a Java thing 🤷 Why you sometimes don’t need to do it is because the pools will not create any threads unless you submit jobs to them. So if you don’t use futures or agents in your Clojure program, there is no need to shut down the pools.