GC 是否在 Clojure 中删除 ns 后删除所有对象?

Does GC remove all objects after ns removal in Clojure?

我开发了一些应用程序,它从客户端获取数据并为其创建新的 ns

应用程序在 ns 中进行一些操作后,调用函数等

最后应用 returns 一些输出,然后我删除了 ns (remove-ns)

GC 会删除那个 ns 中的所有数据(对象)吗?

另一个问题是:为每个客户端创建 ns 是否明智? 我需要将客户端彼此隔离,这样就不会有冲突。(并发用户数)

我假设,你在你的命名空间上做 (remove-ns),所以如果你在 clojure 源代码中查看 clojure.core,它会在命名空间符号上调用 Namespace.remove,然后得到从并发哈希图中删除。如果符号只绑定到命名空间,那么它们应该被 gc 清理。

查看您正在使用的版本的 clojure 代码以确保万无一失,如果您有疑问,最好自己测试一下,方法是附加一个探查器,看看这些对象是否确实被删除了在这个函数调用之后。

很遗憾,您的问题没有简单的是或否答案。

What remove-ns[1] does is it calls the static remove method in clojure.lang.Namespace[2],它以事务方式取消映射命名空间的符号在从 ns 名称到命名空间对象的全局映射中。这使得无法对命名空间进行新引用,因为命名空间和完全限定 symbols/vars 是通过命名空间映射解析的,但它不会破坏命名空间或其内容。

如果不存在对未映射命名空间或其内容的引用,那么是的,它将(最终)被垃圾收集。然而,这假设该命名空间中的所有 Vars 都不会逃逸。如果你曾经 require/refer Vars 从这些临时命名空间之一变成长期存在的,你将在两个命名空间之间创建一个永久的 link ,这将导致 "temporary" 命名空间永远不会被删除,除非它也是 ns-unmapped [3].

现代 JVM 使用跟踪垃圾收集器,因此只有在内存压力足以强制执行 GC 运行 时才会对对象进行垃圾收集,并且不会再使用本身不是垃圾的对象。因此,例如,如果您在其自己的沙箱命名空间中为每个会话编译一个函数,返回该函数,调用它,然后将其丢弃并取消映射 可能 可以正常工作的临时命名空间,因为对临时名称空间的唯一显式引用是返回的闭包(已丢弃)和您删除的全局名称空间映射。但确切的行为完全取决于您的应用程序的结构。

在架构层面,可以肯定地说您做错了。 Clojure (eval) 中的编译速度很慢。您真的不应该在 运行 时间动态生成函数,更不用说命名空间了。通过这样做,您正在为自己创建这个体系结构问题,因为您正在(ab)使用旨在成为全局绑定结构(命名空间和 Vars)的内容来保存临时绑定,然后您必须担心清理这些绑定。

如果您确实需要动态绑定或堆栈本地 Var,可以使用一些结构来创建这种短暂的上下文。否则,您可能会通过重构应用程序以更广泛地使用部分应用程序和参数上下文来极大地简化您的应用程序,它们属于更正常的数据使用模式并且将正常进行垃圾收集。