I created Jar with Clojure and Leiningen, and created Native Image from Jar.
Error: Instance that is defined outside of main does not have any methods.
OK: Instance that is defined inside of main have methods correctly.
Why?
GraalVM Version
> java -version
openjdk version "1.8.0_172"
OpenJDK Runtime Environment (build 1.8.0_172-20180626105433.graaluser.jdk8u-src-tar-g-b11)
GraalVM 1.0.0-rc8 (build 25.71-b01-internal-jvmci-0.48, mixed mode)
src/hello/core.clj
(ns hello.core
(:gen-class))
;; Create Instance outside of main.
(def d (java.util.Date.))
(defn -main [& args]
;; Check Java Version
(println "Check Java Version:" (System/getProperty "java.version")) ;; => 1.8.0_172
;; Call Inside Instance Method => OK
;; (println (.getTime (java.util.Date.))) ;; => 1540819744354
;; Call Outside Instance Method => error
(println "Call Instance Method:" (.getTime d))) ;; => error
Run
> lein run
Compiling hello.core
Check Java Version: 1.8.0_172
Call Instance Method: 1540824144643
Create Jar
> lein uberjar
Compiling hello.core
Created ....../target/hello-1.0.0.jar
Created ....../target/hello-1.0.0-standalone.jar
Run Jar
> cd target/
> java -jar hello-1.0.0-standalone.jar
Check Java Version: 1.8.0_172
Call Instance Method: 1540824203620
Create Native Image
> native-image -jar hello-1.0.0-standalone.jar
Build on Server(pid: 14299, port: 53397)
[hello-1.0.0-standalone:14299] classlist: 2,715.99 ms
[hello-1.0.0-standalone:14299] (cap): 1,077.03 ms
[hello-1.0.0-standalone:14299] setup: 1,583.26 ms
[hello-1.0.0-standalone:14299] (typeflow): 4,502.79 ms
[hello-1.0.0-standalone:14299] (objects): 2,659.10 ms
[hello-1.0.0-standalone:14299] (features): 94.75 ms
[hello-1.0.0-standalone:14299] analysis: 7,417.43 ms
[hello-1.0.0-standalone:14299] universe: 271.41 ms
[hello-1.0.0-standalone:14299] (parse): 841.99 ms
[hello-1.0.0-standalone:14299] (inline): 900.53 ms
[hello-1.0.0-standalone:14299] (compile): 4,986.20 ms
[hello-1.0.0-standalone:14299] compile: 7,245.65 ms
[hello-1.0.0-standalone:14299] image: 1,329.76 ms
[hello-1.0.0-standalone:14299] write: 577.77 ms
[hello-1.0.0-standalone:14299] [total]: 21,193.99 ms
Run Native Image
Check Java Version: 1.8.0_172
Exception in thread "main" java.lang.IllegalArgumentException: No matching field found: getTime for class java.util.Date
at java.lang.Throwable.<init>(Throwable.java:265)
at java.lang.Exception.<init>(Exception.java:66)
at java.lang.RuntimeException.<init>(RuntimeException.java:62)
at java.lang.IllegalArgumentException.<init>(IllegalArgumentException.java:52)
at clojure.lang.Reflector.getInstanceField(Reflector.java:271)
at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:315)
at hello.core$_main.invokeStatic(core.clj:17)
at hello.core$_main.doInvoke(core.clj:8)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at hello.core.main(Unknown Source)
at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:164)
The problem is solved.
I understood Substrate VM limitations and the behavior of Clojure.
Clojure call method by Reflection, and Substrate VM has LIMITATIONS.
Understanding Class Initialization in GraalVM Native Image Generation
at clojure.lang.Reflector.getInstanceField(Reflector.java:271)
at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:315)
add this code.
(set! *warn-on-reflection* true)
print warning.
> lein run
Compiling hello.core
Reflection warning, hello/core.clj:14:3 - reference to field getTime can't be resolved.
Check Java Version: 1.8.0_172
Call Instance method with TypeHint: 1540830117929
add TypeHint to avoid reflection.
(ns hello.core
(:gen-class))
(set! *warn-on-reflection* true)
;; Create Instance outside of main.
(def d (java.util.Date.))
(defn -main [& args]
;; Check Java Version
(println "Check Java Version:" (System/getProperty "java.version")) ;; => 1.8.0_172
;; Call Inside Instance Method => OK
;; (println (.getTime (java.util.Date.))) ;; => 1540819744354
;; Call Outside Instance Method => error
;; (println "Call Instance Method:" (.getTime d)) ;; => error
;; Call Outside Instance Method with TypeHint => OK
(println "Call Instance Method with TypeHint:" (.getTime ^java.util.Date d))) ;; => 1540819744354
Run Native Image
> ./hello-1.0.0-standalone
Check Java Version: 1.8.0_172
Call Instance method with TypeHint: 1540830495423
The problem is solved.
I understood Substrate VM limitations and the behavior of Clojure.Clojure call method by Reflection, and Substrate VM has LIMITATIONS.
Understanding Class Initialization in GraalVM Native Image Generation
at clojure.lang.Reflector.getInstanceField(Reflector.java:271) at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:315)add this code.
(set! *warn-on-reflection* true)print warning.
> lein run Compiling hello.core Reflection warning, hello/core.clj:14:3 - reference to field getTime can't be resolved. Check Java Version: 1.8.0_172 Call Instance method with TypeHint: 1540830117929add TypeHint to avoid reflection.
(ns hello.core (:gen-class)) (set! *warn-on-reflection* true) ;; Create Instance outside of main. (def d (java.util.Date.)) (defn -main [& args] ;; Check Java Version (println "Check Java Version:" (System/getProperty "java.version")) ;; => 1.8.0_172 ;; Call Inside Instance Method => OK ;; (println (.getTime (java.util.Date.))) ;; => 1540819744354 ;; Call Outside Instance Method => error ;; (println "Call Instance Method:" (.getTime d)) ;; => error ;; Call Outside Instance Method with TypeHint => OK (println "Call Instance Method with TypeHint:" (.getTime ^java.util.Date d))) ;; => 1540819744354Run Native Image
> ./hello-1.0.0-standalone Check Java Version: 1.8.0_172 Call Instance method with TypeHint: 1540830495423
awesome!
Most helpful comment
The problem is solved.
I understood Substrate VM limitations and the behavior of Clojure.
Clojure call method by Reflection, and Substrate VM has LIMITATIONS.
Understanding Class Initialization in GraalVM Native Image Generation
Substrate VM Java Limitations
add this code.
print warning.
add TypeHint to avoid reflection.
Run Native Image