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
|
||||
[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)
|
||||
|
||||
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
|
||||
(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 []
|
||||
`(fn [~'m]
|
||||
(when (> (count (:interfaces ~'m)) 1)
|
||||
|
|
@ -78,7 +91,9 @@
|
|||
["clojure.lang.IFn"
|
||||
`(reify-ifn ~'m)
|
||||
"java.lang.Object"
|
||||
`(reify-object ~'m)]
|
||||
`(reify-object ~'m)
|
||||
"java.lang.Runnable"
|
||||
`(reify-runnable ~'m)]
|
||||
(for [i interfaces]
|
||||
(let [in (.getName ^Class i)]
|
||||
[in
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@
|
|||
java.lang.reflect.Array
|
||||
{:methods [{:name "newInstance"}
|
||||
{:name "set"}]}
|
||||
java.lang.Runnable
|
||||
{:methods [{:name "run"}]}
|
||||
java.net.Inet4Address
|
||||
{:methods [{:name "getHostAddress"}]}
|
||||
java.net.Inet6Address
|
||||
|
|
@ -264,6 +266,9 @@
|
|||
java.lang.System
|
||||
java.lang.Throwable
|
||||
;; java.lang.UnsupportedOperationException
|
||||
java.lang.ref.WeakReference
|
||||
java.lang.ref.ReferenceQueue
|
||||
java.lang.ref.Cleaner
|
||||
java.math.BigDecimal
|
||||
java.math.BigInteger
|
||||
java.math.MathContext
|
||||
|
|
|
|||
|
|
@ -128,3 +128,26 @@
|
|||
(reify
|
||||
java.lang.Object (toString [_] \"foo\")
|
||||
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