Skip to content
Permalink
Browse files

Workaround locking issue in 1.10

  • Loading branch information...
taylorwood committed Apr 9, 2019
1 parent dc49100 commit 12b96b5e9a722b372f153436b1f6827709d0f2ab
Showing with 50 additions and 3 deletions.
  1. +1 −1 .gitignore
  2. +13 −0 README.md
  3. +2 −1 deps.edn
  4. +11 −0 java/src/clojurl/LockFix.java
  5. +23 −1 src/clojurl.clj
@@ -1,3 +1,3 @@
.cpcache
classes
clojurl
/clojurl
@@ -154,3 +154,16 @@ should satisfy
-------------------------
Detected 1 error
```
## Compiling with Clojure 1.10
GraalVM native-image won't work with Clojure's `locking` macro, and Clojure 1.10 depends on a version of clojure.spec
(see [this commit](https://github.com/clojure/spec.alpha/commit/31165fec69ff86129a1ada8b3f50864922dfc88a)) that uses `locking`.
You can workaround this by compiling a Java class with a special locking mechanism, and patching any usages of `locking` e.g. in clojure.spec.
You must first compile the Java class:
```
➜ javac java/src/clojurl/LockFix.java -cp ~/.m2/repository/org/clojure/clojure/1.10.0/clojure-1.10.0.jar
```
Then patch any usages of `locking` and you should be able to compile a native image. See `clojurl.clj` for example.
@@ -1,8 +1,9 @@
{:deps {expound {:mvn/version "0.7.1"}
org.clojure/clojure {:mvn/version "1.9.0"}
org.clojure/clojure {:mvn/version "1.10.0"}
org.clojure/tools.cli {:mvn/version "0.4.1"}
org.martinklepsch/clj-http-lite {:mvn/version "0.4.1"}
hickory {:mvn/version "0.7.1"}}
:paths ["src" "java/src"]
:aliases {:native-image
{:main-opts ["-m clj.native-image clojurl"
"--report-unsupported-elements-at-runtime"
@@ -0,0 +1,11 @@
package clojurl;

import clojure.lang.IFn;

public class LockFix {
static public Object lock(final Object lockee, final IFn f) {
synchronized (lockee) {
return f.invoke();
}
}
}
@@ -6,10 +6,32 @@
[clojure.pprint :refer [pprint]]
[expound.alpha :as expound]
[hickory.core :as hick])
(:gen-class))
(:gen-class)
(:import (clojurl LockFix)))

(set! *warn-on-reflection* true)

(defmacro locking* ;; patched version of clojure.core/locking to workaround GraalVM unbalanced monitor issue
"Executes exprs in an implicit do, while holding the monitor of x.
Will release the monitor of x in all circumstances."
{:added "1.0"}
[x & body]
`(let [lockee# ~x]
(LockFix/lock lockee# (^{:once true} fn* [] ~@body))))

(defn dynaload ;; patched version of clojure.spec.gen.alpha/dynaload to use patched locking macro
[s]
(let [ns (namespace s)]
(assert ns)
(locking* #'clojure.spec.gen.alpha/dynalock
(require (symbol ns)))
(let [v (resolve s)]
(if v
@v
(throw (RuntimeException. (str "Var " s " is not on the classpath")))))))

(alter-var-root #'clojure.spec.gen.alpha/dynaload (constantly dynaload))

(def cli-options
[["-u" "--uri URI" "URI of request"
:id :url

0 comments on commit 12b96b5

Please sign in to comment.
You can’t perform that action at this time.