Java 从JVM线程本地空间卸载Clojure变量

Java 从JVM线程本地空间卸载Clojure变量,java,memory-leaks,clojure,Java,Memory Leaks,Clojure,我正在用Clojure为BaseX编写一个插件,它是通过“lein uberjar”构建的,包含Clojure解释器。在大多数情况下,这很有效 但是——当通过BaseXHTTP实例运行时,评估在Jetty的线程池中进行,而不是在客户端断开连接后丢弃线程 由于加载插件会通过自定义类加载器加载Clojure的类,并且丢弃作为插件入口点的(AOT编译的)对象实例不会丢弃Clojure在线程本地空间中放置的变量,类加载器泄漏导致PermGen空间最终被Clojure解释器的多个实例耗尽 如何解决这个问题

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

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

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

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

此想法可能(也可能不)有效:

  • 不要制作uberjar,将Clojure罐子分开

  • 通过将Clojure jar放入BaseX的主类路径,将其推上类加载器层次结构(编辑启动BasexX服务器的命令行,类似于
    java-cp BaseX.jar;Clojure.jar org.BaseX.BaseXServer

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


  • 这就是我现在正在做的工作。我将其视为一种解决方法,而不是修复方法,因为我认为将Clojure作为BaseX安装的一部分是错误的——例如,每当插件更改其依赖链时就必须修改数据库安装,这是不干净的。好吧,Clojure毕竟是一个完整的语言执行环境,而不仅仅是任何旧的jar依赖。对我来说,这种方法更像是启用BaseX Clojure。所有其他依赖项仍然可以保留在插件的本地。您更改正在使用的Clojure版本的频率并不是很高,甚至可能比升级BaseX本身的频率更低。我希望这是真的——我在Clojure 1.3.0中遇到了一个bug,这迫使我已经升级到1.4 beta系列。(如果我有第二个插件只针对target编写,比如Clojure 1.1,这将是一个非常不幸的情况)。更重要的是,从操作的角度来看,任何jar依赖项不能充当“任何旧jar依赖项”都是非常不幸的。因此,我认为将其视为需要解决的问题是合理的。另一方面,您不会期望能够卸载rt.jar,或者同时运行两个版本的Java。我同意如果你有一个只针对Java1.3的插件,那将是一个非常不幸的情况。这是一个灰色地带,我想说。。。