使用HotswapAgent/DCEVM与Clojure REPL时出现LinkageError。

huangapple 未分类评论52阅读模式
英文:

LinkageError when using HotswapAgent/DCEVM with Clojure REPL

问题

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

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

为了提供更多细节,我已经设置了~/.lein/profiles.clj,以便在:repl配置中,使用当前版本的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"
 
  ... ;; profiles.clj 的其余部分
}}

为了重现问题,我创建了一个最小的混合Leiningen Clojure和Java项目,其中包含一个小的Java类AD,其代码如下:

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 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),但实际上我得到了以下错误:

Execution error (LinkageError) at dcevm-complex-demo.ad/raise-to-power
(ad.clj:10). loader constraint violation: when resolving method 'AD
AD.raiseToPower()' the class loader clojure.lang.DynamicClassLoader
@7c53a0c2 of the current class, dcevm_complex_demo/ad$raise_to_power,
and the class loader 'app' for the method's defining class, AD, have
different Class objects for the type AD used in the signature
(dcevm_complex_demo.ad$raise_to_power is in unnamed module of loader
clojure.lang.DynamicClassLoader @7c53a0c2, parent loader
clojure.lang.DynamicClassLoader @1217a2dd; AD is in unnamed module of
loader 'app')

完整的REPL交互如下图所示:

使用HotswapAgent/DCEVM与Clojure REPL时出现LinkageError。

我该如何使AD的重新加载工作?我怀疑我可能需要更改函数clojure.lang.RT.baseLoader()clojure/lang/RT.java),但我不太确定如何操作。

英文:

I am trying to use HotswapAgent/DCEVM in a mixed Clojure/Java Leiningen project in order to avoid having to restart the REPL after recompiling the Java source code (I am already aware of other approaches to this, such as JRebel and Virgil).

In short, the problem is that I get a LinkageError after reloading a Java class that I recompiled, and it seems like the class does not get reloaded.

To provide more details, I have set up my ~/.lein/profiles.clj so that in the :repl profile, we use the current version of DCEVM JVM found here to run the REPL. This is the relevant portion of 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

To reproduce the problem, I have set up a minimal mixed Leiningen Clojure and Java project with a small Java class AD with this code:

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 + ")";
    }
}

and a small piece of Clojure code that imports this class:

(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))

Then I start a Clojure REPL in Emacs/CIDER, load the dcevm-complex-demo.ad namespace and evaluate the expression (raise-to-power (variable 3.0)) which produces the result AD(value=81.0, deriv=108.0). I then modify the Java source code, for example, I change the line public static int EXPONENT = 4; to public static int EXPONENT = 3; and recompile using lein javac in the terminal. A message in the REPL tells me the class AD was reloaded. But then when I re-evaluate the expression (raise-to-power (variable 3.0)) I would expect the result AD(value=27.0, deriv=27.0), but instead I get this error:

> Execution error (LinkageError) at dcevm-complex-demo.ad/raise-to-power
> (ad.clj:10). loader constraint violation: when resolving method 'AD
> AD.raiseToPower()' the class loader clojure.lang.DynamicClassLoader
> @7c53a0c2 of the current class, dcevm_complex_demo/ad$raise_to_power,
> and the class loader 'app' for the method's defining class, AD, have
> different Class objects for the type AD used in the signature
> (dcevm_complex_demo.ad$raise_to_power is in unnamed module of loader
> clojure.lang.DynamicClassLoader @7c53a0c2, parent loader
> clojure.lang.DynamicClassLoader @1217a2dd; AD is in unnamed module of
> loader 'app')

This is what the full REPL interaction looks like:

使用HotswapAgent/DCEVM与Clojure REPL时出现LinkageError。

How can I make the reloading of the class AD work? I suspect that I might have to change the function clojure.lang.RT.baseLoader() (clojure/lang/RT.java) but I am not quite sure how to go about that.

答案1

得分: 0

在dcevm8和dcevm11中都存在关于lambda重新定义的问题。这个问题已经在dcevm v11.0.7+1中得到了解决。根据您的日志,这可能会有所帮助。
链接:https://github.com/TravaOpenJDK/trava-jdk-11-dcevm/releases/tag/dcevm-11.0.7+1

英文:

There was a problem with lambda redefinition both in dcevm8 and dcevm11. This issue was resolved in dcevm v11.0.7+1. According your logs it could help.
https://github.com/TravaOpenJDK/trava-jdk-11-dcevm/releases/tag/dcevm-11.0.7+1

huangapple
  • 本文由 发表于 2020年5月4日 16:38:06
  • 转载请务必保留本文链接:https://java.coder-hub.com/61588170.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定