Fork me on GitHub
#graalvm
<
2019-05-11
>
dharrigan12:05:23

So, trying to run a simple "hello-world" type of clojure app - it compiles using native-image, but when I run it, I get this:

dharrigan12:05:31

Exception in thread "main" java.lang.ExceptionInInitializerError
	at com.oracle.svm.core.hub.ClassInitializationInfo.initialize(ClassInitializationInfo.java:287)
	at java.lang.Class.ensureInitialized(DynamicHub.java:437)
	at clojure.lang.Namespace.<init>(Namespace.java:34)
	at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
	at clojure.lang.Var.internPrivate(Var.java:153)
	at palindrome.core.<clinit>(Unknown Source)
	at com.oracle.svm.core.hub.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:347)
	at com.oracle.svm.core.hub.ClassInitializationInfo.initialize(ClassInitializationInfo.java:267)
	at java.lang.Class.ensureInitialized(DynamicHub.java:437)
Caused by: java.io.FileNotFoundException: Could not locate clojure/core__init.class or clojure/core.clj on classpath.
	at clojure.lang.RT.load(RT.java:463)
	at clojure.lang.RT.load(RT.java:426)
	at clojure.lang.RT.doInit(RT.java:468)
	at clojure.lang.RT.<clinit>(RT.java:336)
	at com.oracle.svm.core.hub.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:347)
	at com.oracle.svm.core.hub.ClassInitializationInfo.initialize(ClassInitializationInfo.java:267)
	... 8 more

dharrigan12:05:15

I'm building the app using

dharrigan12:05:46

GraalVM Version 19.0.0 CE

dharrigan12:05:55

Anyone else come up against this issue?

Adrian Smith15:05:32

The solution to my problem was to add (flush) at the end of the program that worked

dharrigan17:05:17

Okay, found the answer. With GraalVM 19.0.0, they have changed the way that classes are initialised at runtime

dharrigan17:05:30

It's all clearly detailed in their release notes for 19.0.0

dharrigan17:05:53

To fix the problem, and to have the native-image run perfectly, you just have to do this (showing an example project.clj)

dharrigan17:05:09

(defproject palindrome "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url ""
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url ""}
  :dependencies [[org.clojure/clojure "1.9.0"]]
  :plugins [[io.taylorwood/lein-native-image "0.3.0"]]
  :native-image {:name "palindromes"
                 :opts ["--report-unsupported-elements-at-runtime"
                        "--initialize-at-build-time"]}
  :main ^:skip-aot palindrome.core
  :repl-options {:init-ns palindrome.core}
  :profiles {:dev {:global-vars {*warn-on-reflection* true
                                 *assert* true}}
             :uberjar {:aot 
                       :all
                       :native-image {:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}}})

dharrigan17:05:37

The incantation is to add in the --initialize-at-build-time flag for graalvm to do it's magic.

dharrigan17:05:35

A very quick and-take-it-with-a-pinch-of-salt-metric

dharrigan17:05:39

java -jar target/palindrome-0.1.0-SNAPSHOT-standalone.jar "foo"  2.35s user 0.27s system 225% cpu 1.161 total

dharrigan17:05:56

./target/palindromes "foo"  0.01s user 0.00s system 88% cpu 0.006 total

dharrigan17:05:05

0.01s for the native image!!!

dharrigan17:05:20

hope this helps others... 🙂