JVM Clojure 如何在后台存储捕获的闭包环境?

问题描述 投票:0回答:1

当我定义一个在外部作用域中捕获其某些变量的函数时,如下所示,Clojure(在 JVM 主机上)实际上如何存储捕获的环境?

(let [small-datastructure (calculate-small-thing)
      large-datastructure (calculate-large-thing)]
  (if *feeling-lucky*
    (fn capturing-closure [] (do-other-thing small-datastructure))
    (use-data large-datastructure))

特别是,函数

capturing-closure
仅引用
small-datastructure
,而不引用
large-datastructure
。当我从此代码返回
capturing-closure
时,
large-datastructure
是否仍会被
capturing-closure
引用,还是会被释放到垃圾回收中?

对于如何准确衡量这一点,我愿意接受直接答案或建议。

lambda clojure scope jvm
1个回答
0
投票

回答我自己的问题——尽管我仍然很欣赏基于对 Clojure/JVM 内部结构的深入了解的答案!

我做了一个小实验,使用

(System/gc)
来强制GC,并使用弱引用来检查GC后对象是否仍然存在于堆上:

(ns gc-test
  (:import [java.lang.ref WeakReference]))

(defn calculate-small-thing [] (vec (range 10)))

(defn calculate-large-thing [] (vec (range 10000000)))

(def closure-use (atom nil))

(defn test-closure-gc []
  (dotimes [i 10]
    (println "Test iteration:" i)
    (let [[weak-small-ref, weak-large-ref]
          (let [small-datastructure (calculate-small-thing)
                weak-small-ref (WeakReference. small-datastructure)
                large-datastructure (calculate-large-thing)
                weak-large-ref (WeakReference. large-datastructure)
                capturing-closure (fn [] (reduce + small-datastructure))]
            ;; Store the closure to prevent it from being garbage collected
            (reset! closure-use capturing-closure)
            ;; Return our weak references
            [weak-small-ref weak-large-ref])]
      ;; Force garbage collection
      (System/gc)
      ;; Sleep briefly to allow GC to complete
      (Thread/sleep 100)
      ;; Sanity-check that small-datastructure is not collected
      (println "Is small-datastructure collected?"
               (nil? (.get weak-small-ref)))
      ;; Check if large-datastructure has been garbage collected
      (println "Is large-datastructure collected?"
               (nil? (.get weak-large-ref))))))

;; Run the test
(test-closure-gc)

输出显示

small-datastructure
仍按预期被引用,并且
large-datastructure
得到可靠收集:

Test iteration: 0
Is small-datastructure collected? false
Is large-datastructure collected? true
Test iteration: 1
Is small-datastructure collected? false
Is large-datastructure collected? true
Test iteration: 2
Is small-datastructure collected? false
Is large-datastructure collected? true
Test iteration: 3
Is small-datastructure collected? false
Is large-datastructure collected? true
Test iteration: 4
Is small-datastructure collected? false
Is large-datastructure collected? true
Test iteration: 5
Is small-datastructure collected? false
Is large-datastructure collected? true
Test iteration: 6
Is small-datastructure collected? false
Is large-datastructure collected? true
Test iteration: 7
Is small-datastructure collected? false
Is large-datastructure collected? true
Test iteration: 8
Is small-datastructure collected? false
Is large-datastructure collected? true
Test iteration: 9
Is small-datastructure collected? false
Is large-datastructure collected? true
© www.soinside.com 2019 - 2024. All rights reserved.