Welcome to my GitHub page
I ❤️ functional programming
Build GraalVM native images with Clojure Deps and CLI tools
License: MIT License
I'm not sure if this is a graal issue or a clj.native-image issue but when attempting to create a native image I keep getting a failure and it generates a fallback image
deps.edn
snippet:
:aliases {:native-image {:main-opts ["-m" "clj.native-image" "server.main"
"--report-unsupported-elements-at-runtime"
"--initialize-at-build-time"
"-Dclojure.compiler.direct-linking=true"
"-H:Name=behr_codes"]
:extra-deps {clj.native-image/clj.native-image
{:git/url "https://github.com/taylorwood/clj.native-image.git"
:sha "7708e7fd4572459c81f6a6b8e44c96f41cdd92d4"}}}}
clj -M:native-image
output:
out.log
$ clojure -A:native-image
Loading fc4.cli.wcb
Compiling fc4.cli.wcb
Exception in thread "main" org.eclipse.aether.resolution.ArtifactResolutionException: Could not find artifact org.clojure:clojure:jar:1.7.0
at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:422)
at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts(DefaultArtifactResolver.java:224)
at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact(DefaultArtifactResolver.java:201)
at org.eclipse.aether.internal.impl.DefaultRepositorySystem.resolveArtifact(DefaultRepositorySystem.java:260)
at clojure.tools.deps.alpha.extensions.maven$get_artifact.invokeStatic(maven.clj:95)
at clojure.tools.deps.alpha.extensions.maven$get_artifact.invoke(maven.clj:91)
at clojure.tools.deps.alpha.extensions.maven$eval395$fn__397.invoke(maven.clj:112)
at clojure.lang.MultiFn.invoke(MultiFn.java:243)
at clojure.tools.deps.alpha$lib_paths$fn__765.invoke(alpha.clj:203)
at clojure.core.protocols$iter_reduce.invokeStatic(protocols.clj:49)
at clojure.core.protocols$fn__7839.invokeStatic(protocols.clj:75)
at clojure.core.protocols$fn__7839.invoke(protocols.clj:75)
at clojure.core.protocols$fn__7781$G__7776__7794.invoke(protocols.clj:13)
at clojure.core$reduce.invokeStatic(core.clj:6748)
at clojure.core$reduce.invoke(core.clj:6730)
at clojure.tools.deps.alpha$lib_paths.invokeStatic(alpha.clj:199)
at clojure.tools.deps.alpha$lib_paths.invoke(alpha.clj:197)
at clojure.tools.deps.alpha$resolve_deps.invokeStatic(alpha.clj:229)
at clojure.tools.deps.alpha$resolve_deps.invoke(alpha.clj:210)
at clj.native_image$deps__GT_classpath.invokeStatic(native_image.clj:12)
at clj.native_image$deps__GT_classpath.invoke(native_image.clj:9)
at clj.native_image$_main.invokeStatic(native_image.clj:61)
at clj.native_image$_main.doInvoke(native_image.clj:43)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.core$apply.invokeStatic(core.clj:657)
at clojure.main$main_opt.invokeStatic(main.clj:317)
at clojure.main$main_opt.invoke(main.clj:313)
at clojure.main$main.invokeStatic(main.clj:424)
at clojure.main$main.doInvoke(main.clj:387)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.main.main(main.java:37)
Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not find artifact org.clojure:clojure:jar:1.7.0
at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:412)
... 32 more
deps.edn
{:paths ["src/main" "src/cli"]
:deps
{org.clojure/core.async {:mvn/version "0.4.474"}
org.clojure/spec.alpha {:mvn/version "0.2.168"}
org.clojure/tools.cli {:mvn/version "0.3.7"}
circleci/clj-yaml {:mvn/version "0.5.6"}
potemkin {:mvn/version "0.4.5"}
expound {:mvn/version "0.7.1"}
com.cognitect/anomalies {:mvn/version "0.1.12"}
;; test.chuck is in the main dependency list, rather than in the test profile,
;; because we’re using one of its generators in a spec in a source file.
;; This means we’ll also need org.clojure/test.check at runtime. Not ideal,
;; but worth it.
com.gfredericks/test.chuck {:mvn/version "0.2.9"}}
:aliases {:dev {:extra-deps {org.clojure/tools.trace {:mvn/version "0.7.9"}
inspectable {:mvn/version "0.2.2"}}}
:test {:extra-paths ["test" "src/test_utils"]
:extra-deps {org.clojure/test.check {:mvn/version "0.10.0-alpha3"}
eftest {:mvn/version "0.5.3"}}}
:test/run {:main-opts ["-m" "fc4.test-runner.runner"]}
:test/coverage
{:extra-deps {cloverage {:mvn/version "1.0.13"}}
:main-opts ["-m" "cloverage.coverage"
"--src-ns-path" "src/main"
"--test-ns-path" "test"
"--runner" ":fc4.test-runner"
"--fail-threshold" "65"
"--codecov"]}
:lint {:extra-deps {github-JamesLaverack/cljfmt-runner
{:git/url "https://github.com/JamesLaverack/cljfmt-runner"
:sha "51f85c9d6cc67107620749ceacd46120647fe107"}}
:main-opts ["-m" "cljfmt-runner.check"]}
:lint/fix {:main-opts ["-m" "cljfmt-runner.fix"]}
:native-image
{:main-opts ["-m clj.native-image fc4.cli.wcb"
"-H:Name=wcb"]
:extra-deps {clj.native-image
{:git/url "https://github.com/taylorwood/clj.native-image.git"
:sha "0f113d46f9f0d07e8a29545c636431ddf5360a7d"}}}
:clj-next {:override-deps {org.clojure/clojure {:mvn/version "1.10.0-alpha6"}}}}
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}
I’m using this software:
/usr/local/
If you’d like to try to reproduce in the context of my project, you can check out this branch.
I’d appreciate any assistance! Thank you!
I'm trying to build a binary for Windows with GraalVM 19.
I installed tools.deps as per https://github.com/clojure/tools.deps.alpha/wiki/clj-on-Windows in a Windows VM.
Right now clj.native-image crashes. This is when calling deps.reader/clojure-env
. The issue is that tools.deps shells out to clojure
(https://github.com/clojure/tools.deps.alpha/blob/0884eb03fda6967204431b59b11a7d56b36bab36/src/main/clojure/clojure/tools/deps/alpha/reader.clj#L19) but apparently this program cannot be resolved, although it is a known command in Powershell itself.
The process exits with this error on Windows with GraalVM 19:
Error: Unrecognized option: --no-server
I have native-image in my PATH but it isn't used. (As the documentation mentions, setting GRAALVM_HOME or having the bin subdirectory of my project contain a symlink to native-image works.)
clj.native-image/src/clj/native_image.clj
Lines 57 to 59 in 567176d
Does it sound reasonable for clj.native-image to make use of a native-image binary that's on one's PATH?
Don't know if it's really a problem, but it appears one can end up with redundant compilations invoking build
.
main-ns
in build
is typically a string IIUC. namespaces
appears to have symbols in it and may end up including the namespace that main-ns
refers to.
Thus, (cons main-ns namespaces)
can end up with a string version of main-ns
as well as a symbol version:
(let [deps-map (merged-deps)
namespaces (mapcat (comp find-namespaces-in-dir io/file) (:paths deps-map))]
(prep-compile-path)
(doseq [ns (distinct (cons main-ns namespaces))]
(println "Compiling" ns)
(compile (symbol ns)))
I have seen "Compiling script" appear twice -- once for the string "script" and once for the symbol script
.
I guess one could do (cons (symbol main-ns) namespaces)
since there is a wrapping distinct
. Not sure if namespaces
will always contain a symbol version of main-ns
.
Just wanted to drop a note that the newest version of tools.deps.alpha contains some api changes (moving towards getting out of alpha). So when you bump to tools.deps.alpha >= 0.9.745, you'll need to change your function clj.native-image/merged-deps. Should be something like (let [{:keys [root-edn user-edn project-edn]} (find-edn-maps)] (merge-edns [root-edn user-edn project-edn]))
(all fns in clojure.tools.deps.alpha).
On Windows I need to pass in a different name for native-image
:
C:\\Users\\IEUser\\Downloads\\graalvm\\graalvm-ce-19.0.0\\bin\\native-image.cmd
It would be more ergonomic if clj.native-image could automatically detect we're on Windows and derive the command name from the GRAALVM_HOME
variable.
Detecting the OS name can be done as follows:
(System/getProperty "os.name") ;;=> "Windows 10"
In the README, it suggests setting up deps.edn
as:
{:aliases {:native-image {...}}
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}
But this will enable direct-linking in all contexts, even during development (where it may not be desired).
What about limiting direct-linking to the native-image alias, e.g.:
{:aliases {:native-image {...
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}}}
Would that work equally well?
I get following error calling the clj.native-image function like this:
clj -A:native-image -m clj.native-image core ~/Downloads/graalvm/bin/native-image --verbose
Loading core
Compiling core
Building native image 'core' with classpath 'classes:src:/home/j/.m2/repository/org/clojure/clojure/1.9.0/clojure-1.9.0.jar:/home/j/.m2/repository/org/clojure/spec.alpha/0.1.143/spec.alpha-0.1.143.jar:/home/j/.m2/repository/org/clojure/core.specs.alpha/0.1.24/core.specs.alpha-0.1.24.jar'
Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.String cannot be cast to clojure.lang.IPersistentCollection
at clojure.core$conj__5112.invokeStatic(core.clj:82)
at clojure.core$conj__5112.invoke(core.clj:82)
at clj.native_image$build_native_image.invokeStatic(native_image.clj:30)
at clj.native_image$build_native_image.invoke(native_image.clj:27)
at clj.native_image$_main.invokeStatic(native_image.clj:53)
at clj.native_image$_main.doInvoke(native_image.clj:40)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.core$apply.invokeStatic(core.clj:657)
at clojure.main$main_opt.invokeStatic(main.clj:317)
at clojure.main$main_opt.invoke(main.clj:313)
at clojure.main$main.invokeStatic(main.clj:424)
at clojure.main$main.doInvoke(main.clj:387)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.main.main(main.java:37)
Looking in line 30, I can see this conj failing:
(conj opts "--no-server")
I guess the opts is a string here and not something that can be used with conj.
Thanks for making this repo!
This is probably PEBKAC as usual, but maybe you wouldn’t mind doing my debugging for me?
I thought it’d be helpful to have a fast executable for cljfmt so I could run it as a git pre-commit hook.
cljfmt itself doesn’t use tools.deps, but cljfmt-runner does, so I thought I’d see if I could use this project to build a native executable of that project.
Unfortunately after adding the native-image
profile and the jvm-opts
to deps.edn
and (:gen-class)
to the ns
forms, I’m just getting this:
cljfmt-runner $ clojure -A:native-image-check
Loading cljfmt-runner.check
Exception in thread "main" java.io.FileNotFoundException: Could not locate cljfmt-runner/check__init.class, cljfmt-runner/check.clj or cljfmt-runner/check.cljc on classpath.
at clojure.lang.RT.load(RT.java:464)
at clojure.lang.RT.load(RT.java:426)
at clojure.core$load$fn__6735.invoke(core.clj:6098)
at clojure.core$load.invokeStatic(core.clj:6097)
at clojure.core$load.doInvoke(core.clj:6081)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clj.native_image$_main.invokeStatic(native_image.clj:60)
at clj.native_image$_main.doInvoke(native_image.clj:50)
...
Here’s the new stuff I added to deps.edn
:
Bottom of deps.edn
:native-image-check {:main-opts ["-m clj.native-image cljfmt-runner.check"
"-H:Name=cljfmt-check"]
:extra-deps {clj.native-image
{:git/url "https://github.com/taylorwood/clj.native-image.git"
:sha "2dd7ce300e152d56a65dfc28de7d860981bf85cf"}}}}
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}
And:
ns
form from src/cljfmt_runner/check.clj
(ns cljfmt-runner.check
(:require [cljfmt.core :as cljfmt]
[cljfmt-runner.core :refer :all]
[cljfmt-runner.diff :as diff])
;; Required for compilation to a “native image” executable via GraalVM.
(:gen-class))
If you’d like, you can check out my branch to reproduce.
Thanks!
@sogaiu reported an issue on Windows where the classpath is hitting some length limit.
For Java 9 and up, it's possible to specify a classpath file (that contains the classpath argument) rather than passing the classpath itself as an argument. It might be possible to workaround the length issue with that.
When additional aliases add extra deps/paths and are added to the classpath, they are not included in the classpath clj.native-image uses. I've added a demo here: https://github.com/lvh/jdnsmith
deps.edn:
{:deps {org.clojure/clojure {:mvn/version "1.10.0"}
org.clojure/data.json {:mvn/version "0.2.6"}}
:aliases
{:srctwo
{:extra-deps {camel-snake-kebab {:mvn/version "0.4.0"}}
:extra-paths ["srctwo/"]}
:native-image
{:main-opts ["-m clj.native-image jdnsmith.core"
"--report-unsupported-elements-at-runtime"
"--initialize-at-build-time"
"-H:Name=json2edn"]
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]
:extra-deps
{clj.native-image
{:git/url "https://github.com/taylorwood/clj.native-image.git"
:sha "567176ddb0f7507c8b0969e0a10f60f848afaf7d"}}}
:uberdeps
{:extra-deps {uberdeps {:mvn/version "0.1.3"}}
:main-opts ["-m" "uberdeps.uberjar"]}
:pack
{:extra-deps
{pack/pack.alpha {:git/url "https://github.com/juxt/pack.alpha.git"
:sha "81b9e47d992b17aa3e3af1a47aed1f0287ebe9b8"}}
:main-opts ["-m"]}
:depstar
{:extra-deps
{seancorfield/depstar {:mvn/version "0.2.1"}}}}}
When running native-image, only the toplevel :deps/:paths are used, even if the srctwo
alias is active:
jdnsmith ➤ clj -A:srctwo:native-image git:master
Compiling jdnsmith.core
Building native image with classpath 'classes:src:/home/lvh/.m2/repository/org/clojure/clojure/1.10.0/clojure-1.10.0.jar:/home/lvh/.m2/repository/org/clojure/data.json/0.2.6/data.json-0.2.6.jar:/home/lvh/.m2/repository/org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176.jar:/home/lvh/.m2/repository/org/clojure/core.specs.alpha/0.2.44/core.specs.alpha-0.2.44.jar'
[json2edn:39963] classlist: 3,244.86 ms
[json2edn:39963] (cap): 807.98 ms
[json2edn:39963] setup: 1,906.19 ms
[json2edn:39963] (typeflow): 5,416.23 ms
[json2edn:39963] (objects): 2,571.23 ms
[json2edn:39963] (features): 168.06 ms
[json2edn:39963] analysis: 8,290.84 ms
[json2edn:39963] (clinit): 143.40 ms
[json2edn:39963] universe: 393.45 ms
[json2edn:39963] (parse): 323.02 ms
[json2edn:39963] (inline): 1,342.40 ms
[json2edn:39963] (compile): 3,429.39 ms
[json2edn:39963] compile: 5,508.10 ms
[json2edn:39963] image: 711.84 ms
[json2edn:39963] write: 114.21 ms
[json2edn:39963] [total]: 20,309.50 ms
(note camel-snake-kebab missing from classpath, srctwo missing from classpath).
This is contrary to the behavior of clj in general, both the repl (:extra-paths/:extra-deps are how you introduce new code paths or deps) but also third party build tools like depstar:
jdnsmith ➤ clojure -A:srctwo:depstar -m hf.depstar.uberjar depstar.jar git:master*
Building uber jar: depstar.jar
jdnsmith ➤ jar -tvf depstar.jar | (grep camel - > /dev/null && echo "csk in jar") git:master*
csk in jar
jdnsmith ➤ jar -tvf depstar.jar | (grep moresource - > /dev/null && echo "jdnsmith/moresource.clj in jar") git:master*
jdnsmith/moresource.clj in jar
👋 hi @taylorwood, I hope you don’t mind me dropping another general “I have no idea what I’m doing” issue on you. Given that it’s been almost exactly a year since my last attempt (#2) I wanted to try again to create a native image of my project. I didn’t get very far and I don’t really understand the error output, so I’m hoping you might have a few minutes to point me in the right direction.
I’m running MacOS 10.14.5 and I’m using GraalVM CE 19.2.1 and native-image 19.2.1.
Here’s the profile I added to my deps.edn
:
:native-image {:extra-deps {taylorwood/clj.native-image {:git/url "https://github.com/taylorwood/clj.native-image"
:sha "b3823a48be75122b9671c86ce5353a85589ef15f"}}
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]
:main-opts ["-m clj.native-image fc4.io.cli.main"
"--initialize-at-build-time"
"--no-fallback"
"--allow-incomplete-classpath"
"--report-unsupported-elements-at-runtime"
"-H:Name=target/fc4"]}
and here’s the output when I run clojure -A:native-image
:
~/dev/fc4-framework/tool $ clojure -A:native-image
Compiling fc4.io.cli.main
Reflection warning, clj_chrome_devtools/automation.clj:61:5 - reference to field close on java.lang.Object can't be resolved.
Compiling fc4.files
Compiling fc4.image-utils
Compiling fc4.integrations.structurizr.express.chromium-renderer
Compiling fc4.integrations.structurizr.express.export
Compiling fc4.integrations.structurizr.express.format
Compiling fc4.integrations.structurizr.express.snap
Compiling fc4.integrations.structurizr.express.spec
Compiling fc4.integrations.structurizr.express.yaml
Compiling fc4.io.cli.main
Compiling fc4.io.cli.util
Compiling fc4.io.dsl
Compiling fc4.io.render
Compiling fc4.io.util
Compiling fc4.io.watch
Compiling fc4.io.yaml
Compiling fc4.model
Compiling fc4.rendering
Compiling fc4.spec
Compiling fc4.styles
Compiling fc4.util
Compiling fc4.view
Compiling fc4.yaml
[target/fc4:64156] classlist: 10,049.22 ms
[target/fc4:64156] (cap): 1,399.70 ms
[target/fc4:64156] setup: 2,605.29 ms
[target/fc4:64156] analysis: 105,538.54 ms
Error: Unsupported features in 8 methods
Detailed message:
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandle.bindTo(Object)
Trace:
at parsing java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandleImpl.java:221)
Call path from entry point to java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandle, MethodType, boolean, boolean):
at java.lang.invoke.MethodHandleImpl.makePairwiseConvertByEditor(MethodHandleImpl.java:207)
at java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:194)
at java.lang.invoke.MethodHandleImpl.makePairwiseConvert(MethodHandleImpl.java:380)
at java.lang.invoke.MethodHandle.asTypeUncached(MethodHandle.java:776)
at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
at com.oracle.svm.reflect.MethodHandle_invokeWithArguments_9dda848d0201e4e26c7b3711f56411a6605b9b6f_29.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Method.java:498)
at clojure.core$bean$fn__7197$fn__7198.invoke(core_proxy.clj:408)
at clojure.lang.AFn.run(AFn.java:22)
at java.lang.Thread.run(Thread.java:748)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:460)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandleImpl$BindCaller.prepareForInvoker(MethodHandle)
Trace:
at parsing java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(MethodHandleImpl.java:1166)
Call path from entry point to java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(Class):
at java.lang.invoke.MethodHandleImpl$BindCaller.makeInjectedInvoker(MethodHandleImpl.java:1141)
at java.lang.invoke.MethodHandleImpl$BindCaller.access$300(MethodHandleImpl.java:1122)
at java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1175)
at java.lang.invoke.MethodHandleImpl$BindCaller$1.computeValue(MethodHandleImpl.java:1173)
at com.oracle.svm.core.jdk.Target_java_lang_ClassValue.get(JavaLangSubstitutions.java:514)
at java.lang.invoke.MethodHandleImpl.makeArrayElementAccessor(MethodHandleImpl.java:76)
at java.lang.invoke.MethodHandles.arrayElementGetter(MethodHandles.java:1825)
at java.lang.invoke.LambdaFormEditor.spreadArgumentsForm(LambdaFormEditor.java:550)
at java.lang.invoke.MethodHandle.asSpreader(MethodHandle.java:874)
at java.lang.invoke.Invokers.spreadInvoker(Invokers.java:158)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
at com.oracle.svm.reflect.MethodHandle_invokeWithArguments_9dda848d0201e4e26c7b3711f56411a6605b9b6f_29.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Method.java:498)
at clojure.core$bean$fn__7197$fn__7198.invoke(core_proxy.clj:408)
at clojure.lang.AFn.run(AFn.java:22)
at java.lang.Thread.run(Thread.java:748)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:460)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Invoke with MethodHandle argument could not be reduced to at most a single call: java.lang.invoke.MethodHandleImpl.buildVarargsArray(MethodHandle, MethodHandle, int)
Trace:
at parsing java.lang.invoke.MethodHandleImpl.varargsArray(MethodHandleImpl.java:1634)
Call path from entry point to java.lang.invoke.MethodHandleImpl.varargsArray(Class, int):
at java.lang.invoke.MethodHandleImpl.varargsArray(MethodHandleImpl.java:1611)
at java.lang.invoke.MethodHandleImpl$IntrinsicMethodHandle.asCollector(MethodHandleImpl.java:1363)
at java.lang.invoke.MethodHandleImpl$AsVarargsCollector.asTypeUncached(MethodHandleImpl.java:502)
at java.lang.invoke.MethodHandle.asType(MethodHandle.java:761)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
at com.oracle.svm.reflect.MethodHandle_invokeWithArguments_9dda848d0201e4e26c7b3711f56411a6605b9b6f_29.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Method.java:498)
at clojure.core$bean$fn__7197$fn__7198.invoke(core_proxy.clj:408)
at clojure.lang.AFn.run(AFn.java:22)
at java.lang.Thread.run(Thread.java:748)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:460)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of javax.net.ssl.SSLContext are allowed in the image heap as this class should be initialized at image runtime. To see how this object got instantiated use -H:+TraceClassInitialization.
Trace:
at parsing org.httpkit.client.HttpClient.exec(HttpClient.java:347)
Call path from entry point to org.httpkit.client.HttpClient.exec(String, RequestConfig, SSLEngine, IRespListener):
at org.httpkit.client.HttpClient.exec(HttpClient.java:269)
at org.httpkit.client$request.invokeStatic(client.clj:258)
at org.httpkit.client$request.doInvoke(client.clj:152)
at clojure.lang.RestFn.applyTo(RestFn.java:139)
at fc4.io.cli.main.main(Unknown Source)
at com.oracle.svm.core.JavaMainWrapper.runCore(JavaMainWrapper.java:151)
at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:186)
at com.oracle.svm.core.code.IsolateEnterStub.JavaMainWrapper_run_5087f5482cc9a6abc971913ece43acb471d2631b(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of javax.net.ssl.SSLContext are allowed in the image heap as this class should be initialized at image runtime. To see how this object got instantiated use -H:+TraceClassInitialization.
Trace:
at parsing org.httpkit.client.SslContextFactory.trustAnybody(SslContextFactory.java:36)
Call path from entry point to org.httpkit.client.SslContextFactory.trustAnybody():
at org.httpkit.client.SslContextFactory.trustAnybody(SslContextFactory.java:36)
at org.httpkit.client$coerce_req.invokeStatic(client.clj:68)
at org.httpkit.client$coerce_req.invoke(client.clj:59)
at instaparse.auto_flatten_seq.FlattenOnDemandVector.applyTo(auto_flatten_seq.clj:270)
at fc4.io.cli.main.main(Unknown Source)
at com.oracle.svm.core.JavaMainWrapper.runCore(JavaMainWrapper.java:151)
at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:186)
at com.oracle.svm.core.code.IsolateEnterStub.JavaMainWrapper_run_5087f5482cc9a6abc971913ece43acb471d2631b(generated:0)
Error: type is not available in this platform: com.oracle.svm.hosted.NativeImageGenerator
Trace: object java.lang.Class[]
object java.lang.invoke.MethodType
object java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
object java.util.concurrent.ConcurrentHashMap$Node
object java.util.concurrent.ConcurrentHashMap$Node[]
object java.util.concurrent.ConcurrentHashMap
object java.lang.invoke.MethodType$ConcurrentWeakInternSet
method java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean)
Call path from entry point to java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean):
at java.lang.invoke.MethodType.makeImpl(MethodType.java:301)
at java.lang.invoke.MethodType.methodType(MethodType.java:206)
at com.oracle.svm.reflect.MethodType_methodType_9d13644056a712f9cdb73fb2ef8b26f65294abe9_35.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Method.java:498)
at clojure.core$bean$fn__7197$fn__7198.invoke(core_proxy.clj:408)
at clojure.lang.AFn.run(AFn.java:22)
at java.lang.Thread.run(Thread.java:748)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:460)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0)
Error: type is not available in this platform: com.oracle.svm.hosted.lambda.LambdaSubstitutionType
Trace: object java.lang.invoke.MethodType
object java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
object java.util.concurrent.ConcurrentHashMap$Node
object java.util.concurrent.ConcurrentHashMap$Node[]
object java.util.concurrent.ConcurrentHashMap
object java.lang.invoke.MethodType$ConcurrentWeakInternSet
method java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean)
Call path from entry point to java.lang.invoke.MethodType.makeImpl(Class, Class[], boolean):
at java.lang.invoke.MethodType.makeImpl(MethodType.java:301)
at java.lang.invoke.MethodType.methodType(MethodType.java:206)
at com.oracle.svm.reflect.MethodType_methodType_9d13644056a712f9cdb73fb2ef8b26f65294abe9_35.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Method.java:498)
at clojure.core$bean$fn__7197$fn__7198.invoke(core_proxy.clj:408)
at clojure.lang.AFn.run(AFn.java:22)
at java.lang.Thread.run(Thread.java:748)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:460)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0)
Error: unbalanced monitors: mismatch at monitorexit, 96|LoadField#lockee__5436__auto__ != 3|LoadField#lockee__5436__auto__
Call path from entry point to clojure.spec.gen.alpha$dynaload$fn__2628.invoke():
at clojure.spec.gen.alpha$dynaload$fn__2628.invoke(alpha.clj:21)
at clojure.lang.AFn.run(AFn.java:22)
at java.lang.Thread.run(Thread.java:748)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:460)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0)
Original exception that caused the problem: org.graalvm.compiler.code.SourceStackTraceBailoutException$1: unbalanced monitors: mismatch at monitorexit, 96|LoadField#lockee__5436__auto__ != 3|LoadField#lockee__5436__auto__
at clojure.spec.gen.alpha$dynaload$fn__2628.invoke(alpha.clj:22)
Caused by: org.graalvm.compiler.core.common.PermanentBailoutException: unbalanced monitors: mismatch at monitorexit, 96|LoadField#lockee__5436__auto__ != 3|LoadField#lockee__5436__auto__
at org.graalvm.compiler.java.BytecodeParser.bailout(BytecodeParser.java:3761)
at org.graalvm.compiler.java.BytecodeParser.genMonitorExit(BytecodeParser.java:2703)
at org.graalvm.compiler.java.BytecodeParser.processBytecode(BytecodeParser.java:5136)
at org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3267)
at org.graalvm.compiler.java.BytecodeParser.processBlock(BytecodeParser.java:3074)
at org.graalvm.compiler.java.BytecodeParser.build(BytecodeParser.java:976)
at org.graalvm.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:870)
at org.graalvm.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:84)
at org.graalvm.compiler.phases.Phase.run(Phase.java:49)
at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:197)
at org.graalvm.compiler.phases.Phase.apply(Phase.java:42)
at org.graalvm.compiler.phases.Phase.apply(Phase.java:38)
at com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:221)
at com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:340)
at com.oracle.graal.pointsto.flow.MethodTypeFlow.doParse(MethodTypeFlow.java:310)
at com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureParsed(MethodTypeFlow.java:300)
at com.oracle.graal.pointsto.flow.MethodTypeFlow.addContext(MethodTypeFlow.java:107)
at com.oracle.graal.pointsto.flow.SpecialInvokeTypeFlow.onObservedUpdate(InvokeTypeFlow.java:421)
at com.oracle.graal.pointsto.flow.TypeFlow.notifyObservers(TypeFlow.java:343)
at com.oracle.graal.pointsto.flow.TypeFlow.update(TypeFlow.java:385)
at com.oracle.graal.pointsto.flow.SourceTypeFlowBase.update(SourceTypeFlowBase.java:121)
at com.oracle.graal.pointsto.BigBang$2.run(BigBang.java:510)
at com.oracle.graal.pointsto.util.CompletionExecutor.lambda$execute$0(CompletionExecutor.java:171)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Error: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
Error: Image build request failed with exit status 1
My guess is that you could walk me through fixing the “unsupported features” but that last error, the “unbalanced monitors” error — that looks familiar, IIRC that’s related to some incompatibility between GraalVM/native-image and certain code paths in the Clojure runtime… which might be non-work-around-able? If that’s the case, if we’re stuck, then there’s no need to resolve the other errors… but I’d appreciate whatever pointers you’d care to share!
If it helps, feel free to take a look at my branch of my project with that profile added.
(Also, if you’ll be at the Conj next month in Raleigh, I’ll be there too and I’d love to catch up!)
If I use the alias below to make a native image that includes support for js, I somehow end up with an executable called js
instead of the expected name (optikon
). This is minor but it may indicate some error in the parsing of the command line parameters:
{:native-image {:extra-deps {clj.native-image {:git/url "https://github.com/taylorwood/clj.native-image.git"
:sha "498baa963e914fd817dbf33ea251729efd0c8f95"}}
:main-opts ["-m clj.native-image optikon.core"
"-H:Name=optikon"
"--language:js"]}
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}
In my deps.edn
, I have the following setup:
{:paths []
:aliases {:clj {:extra-paths ["src/clj"]}
:native-image {:main-opts ["-m clj.native-image namespace.core"]}}}
And my main namespace is in src/clj/namespace/core.clj
.
When trying to build with clj -A:clj:native-image
I get:
Error: Main entry point class 'namespace.core' not found.
It seems that :extra-paths
from active aliases are not taken into account when finding files to compile.
Since b3823a4 I'm getting errors like:
Error: Unsupported features in 12 methods
Detailed message:
Error: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved type during parsing: clojure.tools.reader.reader_types.IPushbackReader. To diagnose the issue you can use the --allow-incomplete-classpath option. The missing type is then reported at run time when it is accessed the first time.
Trace:
at parsing rewrite_clj.reader$unread.invokeStatic(reader.clj:115)
Call path from entry point to rewrite_clj.reader$unread.invokeStatic(Object, Object):
at rewrite_clj.reader$unread.invokeStatic(reader.clj:112)
at rewrite_clj.reader$unread.invoke(reader.clj:112)
at clojure.tools.reader.default_data_readers.proxy$java.lang.ThreadLocal$ff19274a.equals(Unknown Source)
at java.util.HashMap.getNode(HashMap.java:579)
at java.util.HashMap.get(HashMap.java:557)
at com.oracle.svm.jni.access.JNIReflectionDictionary.getFieldNameByID(JNIReflectionDictionary.java:278)
at com.oracle.svm.jni.functions.JNIFunctions.ToReflectedField(JNIFunctions.java:836)
at com.oracle.svm.core.code.IsolateEnterStub.JNIFunctions_ToReflectedField_80d8233579d5215df0227b770e5c01228a0de9b9(generated:0)
When I try to build the same project by first building an uberjar and handing that to native-image, I don't get those errors.
Upon close inspection of the classes directory that clj.native-image creates for compilation of class files, I noticed that the set of .class files contained differs from what's contained in the uberjar.
One difference is that while the uberjar contains class files for tools.reader.reader_types, the clj.native-image's classes directory hierarchy does not (though it does have other tools.reader-related class files).
When I do (compile 'script)
from the project (without the clj.native-image alias enabled), I do get those class files.
On a possibly related note, it appears that the use of clj.native-image (since the aforementioned commit), affects the version of tools.reader on the classpath, which happens to be something used by the project in question.
(I wonder if using something like mranderson to "vendor" clj.native-image's dependencies might be desirable to not affect the classpath.)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.