我正在尝试在混合的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交互如下所示:
如何使
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