Skip to content

Commit 12b96b5

Browse files
committed
Workaround locking issue in 1.10
1 parent dc49100 commit 12b96b5

File tree

5 files changed

+50
-3
lines changed

5 files changed

+50
-3
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
.cpcache
22
classes
3-
clojurl
3+
/clojurl

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,16 @@ should satisfy
154154
-------------------------
155155
Detected 1 error
156156
```
157+
158+
## Compiling with Clojure 1.10
159+
160+
GraalVM native-image won't work with Clojure's `locking` macro, and Clojure 1.10 depends on a version of clojure.spec
161+
(see [this commit](https://github.com/clojure/spec.alpha/commit/31165fec69ff86129a1ada8b3f50864922dfc88a)) that uses `locking`.
162+
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.
163+
164+
You must first compile the Java class:
165+
```
166+
➜ javac java/src/clojurl/LockFix.java -cp ~/.m2/repository/org/clojure/clojure/1.10.0/clojure-1.10.0.jar
167+
```
168+
169+
Then patch any usages of `locking` and you should be able to compile a native image. See `clojurl.clj` for example.

deps.edn

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{:deps {expound {:mvn/version "0.7.1"}
2-
org.clojure/clojure {:mvn/version "1.9.0"}
2+
org.clojure/clojure {:mvn/version "1.10.0"}
33
org.clojure/tools.cli {:mvn/version "0.4.1"}
44
org.martinklepsch/clj-http-lite {:mvn/version "0.4.1"}
55
hickory {:mvn/version "0.7.1"}}
6+
:paths ["src" "java/src"]
67
:aliases {:native-image
78
{:main-opts ["-m clj.native-image clojurl"
89
"--report-unsupported-elements-at-runtime"

java/src/clojurl/LockFix.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package clojurl;
2+
3+
import clojure.lang.IFn;
4+
5+
public class LockFix {
6+
static public Object lock(final Object lockee, final IFn f) {
7+
synchronized (lockee) {
8+
return f.invoke();
9+
}
10+
}
11+
}

src/clojurl.clj

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,32 @@
66
[clojure.pprint :refer [pprint]]
77
[expound.alpha :as expound]
88
[hickory.core :as hick])
9-
(:gen-class))
9+
(:gen-class)
10+
(:import (clojurl LockFix)))
1011

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

14+
(defmacro locking* ;; patched version of clojure.core/locking to workaround GraalVM unbalanced monitor issue
15+
"Executes exprs in an implicit do, while holding the monitor of x.
16+
Will release the monitor of x in all circumstances."
17+
{:added "1.0"}
18+
[x & body]
19+
`(let [lockee# ~x]
20+
(LockFix/lock lockee# (^{:once true} fn* [] ~@body))))
21+
22+
(defn dynaload ;; patched version of clojure.spec.gen.alpha/dynaload to use patched locking macro
23+
[s]
24+
(let [ns (namespace s)]
25+
(assert ns)
26+
(locking* #'clojure.spec.gen.alpha/dynalock
27+
(require (symbol ns)))
28+
(let [v (resolve s)]
29+
(if v
30+
@v
31+
(throw (RuntimeException. (str "Var " s " is not on the classpath")))))))
32+
33+
(alter-var-root #'clojure.spec.gen.alpha/dynaload (constantly dynaload))
34+
1335
(def cli-options
1436
[["-u" "--uri URI" "URI of request"
1537
:id :url

0 commit comments

Comments
 (0)