【问题标题】:Unloading Clojure vars from JVM thread-local space从 JVM 线程本地空间卸载 Clojure 变量
【发布时间】:2012-04-10 16:58:43
【问题描述】:

我正在 Clojure 中为 BaseX 编写一个插件,通过“lein uberjar”构建,其中包含 Clojure 解释器。在大多数情况下,这很有效。

但是,当通过 BaseX HTTP 实例运行时,评估发生在 Jetty 的线程池中,而不是在客户端断开连接后丢弃线程。

由于加载插件通过自定义类加载器加载 Clojure 的类,并且丢弃充当插件入口点的(AOT 编译的)对象实例不会丢弃 Clojure 在线程本地空间中放置的变量,类加载器泄漏结果是 PermGen 空间最终被 Clojure 解释器的多个实例耗尽。

如何解决?如有必要,我可以对 BaseX 的模块加载/卸载机制进行合理的非 Clojure 特定更改。

【问题讨论】:

    标签: java memory-leaks clojure


    【解决方案1】:

    这个想法可能(或可能不会)有效:

    1. 不要制作 uberjar,将 Clojure jar 分开;

    2. 通过将 Clojure jar 放入 BaseX 的主类路径中,将它们推到类加载器层次结构中(编辑启动 BasexX 服务器的命令行,类似于 java -cp BaseX.jar;clojure.jar org.basex.BaseXServer);

    3. 将您的插件打包为一个 jar,其中仅包含您的代码,并依赖主类路径中已经存在的 Clojure 类。

    【讨论】:

    • 这实际上就是我现在正在做的一种解决方法。我将其视为一种解决方法,而不是修复方法,因为我认为将 Clojure 作为 BaseX 安装的一部分只是错误的事情——例如,每当插件更改其依赖链时都必须修改数据库安装是根本不干净。
    • 嗯,Clojure 毕竟是一个完整的语言执行环境,而不仅仅是任何旧的 jar 依赖项。对我来说,这种方法更像是启用 BaseX Clojure。所有其他依赖项仍然可以保留在插件本地。您更改所使用的 Clojure 版本的频率并不高,甚至可能比升级 BaseX 本身的频率还要低。
    • 我希望这是真的——我在 Clojure 1.3.0 中遇到了一个错误,迫使我已经迁移到 1.4 beta 系列。 (如果我有第二个插件仅针对目标编写,例如 Clojure 1.1,这将是一个非常不幸的情况)。更重要的是——对于 any jar 依赖不能充当“只是任何旧的 jar 依赖”,从操作的角度来看,有点不幸。因此,我认为将其视为需要解决的问题是合理的。
    • 另一方面,您不希望能够卸载 rt.jar,或同时针对两个版本的 Java 运行。我同意如果你有一个只针对 Java 1.3 的插件,那将是一个非常不幸的情况。这是一个灰色地带,我想说...
    猜你喜欢
    • 2018-05-06
    • 2011-05-14
    • 2023-04-09
    • 2010-10-01
    • 1970-01-01
    • 2014-03-03
    • 1970-01-01
    • 2014-09-07
    相关资源
    最近更新 更多