LinkageError при использовании HotswapAgent / DCEVM с Clojure REPL - PullRequest
0 голосов
/ 04 мая 2020

Я пытаюсь использовать HotswapAgent / DCEVM в смешанном проекте Clojure / Java Leiningen, чтобы избежать необходимости перезапуска REPL после перекомпиляции исходного кода Java (мне уже известно о другие подходы к этому, такие как JRebel и Virgil).

Короче говоря, проблема в , что я получаю LinkageError после перезагрузки класса Java, который я перекомпилировал, и кажется, что класс не перезагружается.

Чтобы получить более подробную информацию, я настроил свой ~/.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"

  ... ;; Rest of 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 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))

Затем я запускаю REPL Clojure в Emacs / CIDER, загружаю пространство имен 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), но вместо этого получаю эту ошибку:

Ошибка выполнения (LinkageError) в dcevm-complex-demo.ad / повышение власти (ad.clj: 10). Нарушение ограничения загрузчика: при разрешении метода AD AD.raiseToPower () загрузчик класса clojure.lang.DynamicClassLoader @ 7c53a0c2 текущего класса, dcevm_complex_demo / ad $ поднимает_to_power и загрузчик классов app для класса, определяющего метод, AD , иметь разные объекты Class для типа AD, используемого в подписи (dcevm_complex_demo.ad $ lift_to_power находится в неназванном модуле загрузчика clojure.lang.DynamicClassLoader @ 7c53a0c2, родительский загрузчик clojure.lang.DynamicClassLoader @ 1217a2dd; AD находится в неназванном модуле loader 'app')

Вот как выглядит полное взаимодействие REPL:

REPL interaction

Как я могу заставить перегрузить класс AD работать? Я подозреваю, что мне, возможно, придется изменить функцию clojure.lang.RT.baseLoader() ( clojure / lang / RT. java), но я не совсем уверен, как go узнать об этом.

...