Expose a subset of java.lang.ref to enable hooking into the destruction/GC of objects (#1359)
* reify java.lang.Object with optional toString and finalize * reify java.lang.Runnable * reflection support for java.lang.Runnable * java.lang.ref.* class exposure * test for detection of garbage collection of Object * added change to changelog
This commit is contained in:
parent
c4c76d58ac
commit
ea4f56886d
4 changed files with 48 additions and 1 deletions
|
|
@ -5,6 +5,10 @@ For a list of breaking changes, check [here](#breaking-changes).
|
||||||
A preview of the next release can be installed from
|
A preview of the next release can be installed from
|
||||||
[babashka-dev-builds](https://github.com/babashka/babashka-dev-builds).
|
[babashka-dev-builds](https://github.com/babashka/babashka-dev-builds).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- [#1358](https://github.com/babashka/babashka/issues/1358): Expose a subset of java.lang.ref to enable hooking into the destruction/GC of objects
|
||||||
|
|
||||||
## 0.9.162 (2022-09-04)
|
## 0.9.162 (2022-09-04)
|
||||||
|
|
||||||
Check out our new project: [bbin](https://github.com/babashka/bbin): install any Babashka script or project with one command.
|
Check out our new project: [bbin](https://github.com/babashka/bbin): install any Babashka script or project with one command.
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,19 @@
|
||||||
java.lang.Object
|
java.lang.Object
|
||||||
(toString [this] (toString-fn this)))))
|
(toString [this] (toString-fn this)))))
|
||||||
|
|
||||||
|
(defn reify-runnable [m]
|
||||||
|
(let [methods (:methods m)
|
||||||
|
run-fn (or (get methods 'run)
|
||||||
|
(fn [_]))]
|
||||||
|
(reify
|
||||||
|
sci.impl.types.IReified
|
||||||
|
(getMethods [_] (:methods m))
|
||||||
|
(getInterfaces [_] (:interfaces m))
|
||||||
|
(getProtocols [_] (:protocols m))
|
||||||
|
java.lang.Runnable
|
||||||
|
(run [this] (run-fn this))))
|
||||||
|
)
|
||||||
|
|
||||||
(defmacro gen-reify-fn []
|
(defmacro gen-reify-fn []
|
||||||
`(fn [~'m]
|
`(fn [~'m]
|
||||||
(when (> (count (:interfaces ~'m)) 1)
|
(when (> (count (:interfaces ~'m)) 1)
|
||||||
|
|
@ -78,7 +91,9 @@
|
||||||
["clojure.lang.IFn"
|
["clojure.lang.IFn"
|
||||||
`(reify-ifn ~'m)
|
`(reify-ifn ~'m)
|
||||||
"java.lang.Object"
|
"java.lang.Object"
|
||||||
`(reify-object ~'m)]
|
`(reify-object ~'m)
|
||||||
|
"java.lang.Runnable"
|
||||||
|
`(reify-runnable ~'m)]
|
||||||
(for [i interfaces]
|
(for [i interfaces]
|
||||||
(let [in (.getName ^Class i)]
|
(let [in (.getName ^Class i)]
|
||||||
[in
|
[in
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@
|
||||||
java.lang.reflect.Array
|
java.lang.reflect.Array
|
||||||
{:methods [{:name "newInstance"}
|
{:methods [{:name "newInstance"}
|
||||||
{:name "set"}]}
|
{:name "set"}]}
|
||||||
|
java.lang.Runnable
|
||||||
|
{:methods [{:name "run"}]}
|
||||||
java.net.Inet4Address
|
java.net.Inet4Address
|
||||||
{:methods [{:name "getHostAddress"}]}
|
{:methods [{:name "getHostAddress"}]}
|
||||||
java.net.Inet6Address
|
java.net.Inet6Address
|
||||||
|
|
@ -264,6 +266,9 @@
|
||||||
java.lang.System
|
java.lang.System
|
||||||
java.lang.Throwable
|
java.lang.Throwable
|
||||||
;; java.lang.UnsupportedOperationException
|
;; java.lang.UnsupportedOperationException
|
||||||
|
java.lang.ref.WeakReference
|
||||||
|
java.lang.ref.ReferenceQueue
|
||||||
|
java.lang.ref.Cleaner
|
||||||
java.math.BigDecimal
|
java.math.BigDecimal
|
||||||
java.math.BigInteger
|
java.math.BigInteger
|
||||||
java.math.MathContext
|
java.math.MathContext
|
||||||
|
|
|
||||||
|
|
@ -128,3 +128,26 @@
|
||||||
(reify
|
(reify
|
||||||
java.lang.Object (toString [_] \"foo\")
|
java.lang.Object (toString [_] \"foo\")
|
||||||
clojure.lang.Seqable (seq [_] '(1 2 3)))")))))
|
clojure.lang.Seqable (seq [_] '(1 2 3)))")))))
|
||||||
|
|
||||||
|
(deftest reify-runnable-and-garbage-collection-test
|
||||||
|
(is (bb nil "
|
||||||
|
(def cleaner (java.lang.ref.Cleaner/create))
|
||||||
|
(def deleted? (atom false))
|
||||||
|
(defn make-cleanable-ref []
|
||||||
|
(let [obj (Object.)]
|
||||||
|
(.register cleaner obj
|
||||||
|
(reify java.lang.Runnable
|
||||||
|
(run [_]
|
||||||
|
(reset! deleted? true))))
|
||||||
|
nil))
|
||||||
|
(defn force-gc []
|
||||||
|
(let [t (atom (Object.))
|
||||||
|
wr (java.lang.ref.WeakReference. @t)]
|
||||||
|
(reset! t nil)
|
||||||
|
(while (.get wr)
|
||||||
|
(System/gc)
|
||||||
|
(System/runFinalization))))
|
||||||
|
(make-cleanable-ref)
|
||||||
|
(force-gc)
|
||||||
|
@deleted?
|
||||||
|
")))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue