我正在尝试在混合的Clojure / Java Leiningen项目中使用HotswapAgent/DCEVM,以避免在重新编译Java源代码后不得不重新启动REPL(我已经知道其他方法,例如JRebel和Virgil)。

简而言之,问题是在重新加载我重新编译的Java类之后,我得到一个LinkageError,看来该类没有被重新加载。

为了提供更多详细信息,我已经设置了~/.lein/profiles.clj,以便在:repl配置文件中,我们使用找到的here的当前版本的DCEVM JVM来运行REPL。这是profiles.clj的相关部分:

{:repl
 {:plugins [[cider/cider-nrepl "0.22.4"]]
  :dependencies [[org.clojure/tools.nrepl "0.2.13"]]

  :java-cmd "/home/jonas/local/dcevm-11.0.6+1/bin/java"

  ... ;; Rest of profiles.clj


为了重现该问题,我使用以下代码用小Java类AD设置了minimal mixed Leiningen Clojure and Java project

public class AD {
    public double _value;
    public double _deriv;

    public static int EXPONENT = 4;

    public AD(double value, double deriv) {
        _value = value;
        _deriv = deriv;
    }

    public AD mul(AD x) {
        return new AD(_value*x._value, _value*x._deriv + _deriv*x._value);
    }

    public AD raiseToPower() {
        AD result = new AD(1.0, 0.0);
        for (int i = 0; i < EXPONENT; i++) {
            result = result.mul(this);
        }
        return result;
    }

    public String toString() {
        return "AD(value=" + _value + ", deriv=" + _deriv + ")";
    }
}


以及导入此类的一小段Clojure代码:

(ns dcevm-complex-demo.ad
  (:import AD))

(defn variable [x]
  (AD. (double x) 1.0))

(defn raise-to-power
  "Evaluates f(x) = x^n and f'(x), n being the AD/EXPONENT static variable"
  [^AD ad-x]
  (.raiseToPower ad-x))


然后,我在Emacs / CIDER中启动Clojure REPL,加载dcevm-complex-demo.ad命名空间并评估表达式(raise-to-power (variable 3.0)),该表达式产生结果AD(value=81.0, deriv=108.0)。然后,我修改Java源代码,例如,将行public static int EXPONENT = 4;更改为public static int EXPONENT = 3;,然后在终端中使用lein javac重新编译。 REPL中的一条消息告诉我AD类已重新加载。但是然后当我重新计算表达式(raise-to-power (variable 3.0))时,我期望的结果是AD(value=27.0, deriv=27.0),但是却出现了以下错误:


dcevm-complex-demo.ad/raise-to-power的执行错误(LinkageError)
(ad.clj:10)。加载程序约束冲突:解决方法“ AD”时
AD.raiseToPower()'类加载器clojure.lang.DynamicClassLoader
@ 7c53a0c2当前类的dcevm_complex_demo / ad $ raise_to_power,
该方法的定义类AD的类加载器“ app”具有
签名中使用的AD类型的不同Class对象
(dcevm_complex_demo.ad $ raise_to_power在加载程序的未命名模块中
clojure.lang.DynamicClassLoader @ 7c53a0c2,父加载程序
clojure.lang.DynamicClassLoader @ 1217a2dd;广告位于的未命名模块中
加载程序“ app”)


完整的REPL交互如下所示:

java - 将HotswapAgent/DCEVM与Clojure REPL一起使用时出现LinkageError-LMLPHP

如何使AD类的重载工作?我怀疑我可能不得不更改函数clojure.lang.RT.baseLoader()clojure/lang/RT.java),但是我不确定该如何去做。

最佳答案

dcevm8和dcevm11中的lambda重定义都存在问题。 dcevm v11.0.7 + 1中已解决此问题。根据您的日志可能会有所帮助。
https://github.com/TravaOpenJDK/trava-jdk-11-dcevm/releases/tag/dcevm-11.0.7+1

07-26 06:14
查看更多