Я читал код и документацию, чтобы понять, как перезагрузка класса работает в clojure. Согласно многим веб-сайтам, таким как http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html, всякий раз, когда вы загружаете класс, вы получаете байт-код (через любой механизм данных), конвертируете байт-код в экземпляр класса Class (через defineClass), а затем разрешить (связать) класс с помощью resolveClass. (Определяет ли defineClass неявно вызов resolveClass?). Каждому данному загрузчику классов можно только связать один класс. Если он пытается связать существующий класс, он ничего не делает. Это создает проблему, поскольку вы не можете связать недавно созданный класс, поэтому вам нужно создать новый экземпляр загрузчика классов при каждом перезагрузке класса.
Возвращаясь к clojure, я попытался изучить пути для загрузки классов.
В clojure вы можете определять новые классы несколькими способами в зависимости от того, что вы хотите:
Анонимный класс: материализовать прокси
Именованный класс: deftype defrecord (который использует deftype под капотом) Gen-класс
В конечном итоге эти коды указывают на clojure/src/jvm/clojure/lang/DynamicClassLoader.java
где DynamicClassLoader/defineClass создает экземпляр с супер defineClass и затем кэширует экземпляр. Когда вы хотите получить класс, clojure загрузите вызов toName, который вызывает загрузчик классов и DynamicClassLoader/findClass, который сначала смотрит в кеш, прежде чем делегировать суперкласс (что противоречит способу работы большинства нормальных загрузчиков классов, где они делегируют в первую очередь, чем пытаться сами.) Важным моментом путаницы является следующее: forName документируется, чтобы связать класс до его возвращения, но это означало бы, что вы не можете перезагрузить класс из существующего DynamicClassLoader и вместо этого для создания нового DynamicClassLoader, но я не вижу этого в коде. Я понимаю, что прокси и reify определяют анонимные классы, поэтому их имена различны, поэтому их можно рассматривать так, как если бы это был другой класс. Однако для названных классов это разрушается. В реальном коде clojure вы можете иметь ссылки на старую версию классов и ссылки на новую версию классов одновременно, но попытки создания новых экземпляров класса будут иметь новую версию.
Пожалуйста, объясните, как clojure может перезагружать классы без создания новых экземпляров DynamicClassLoader, если я могу понять механизм перезагрузки классов, я хотел бы расширить эту функциональность перезагрузки до java.class файлов, которые я могу создать с помощью javac.
Примечания: Этот вопрос относится к классу RELOADING, а не просто к динамической загрузке. Перезагрузка означает, что я уже интернировал класс, но хочу ставить новую обновленную версию этого экземпляра.
Я хочу повторить, что неясно, как clojure может перезагрузить определенные классы. Вызов deftype в конечном итоге приводит к вызову clojure.lang.DynamicClassLoader/defineClass. Выполнение этого снова приводит к другому вызову defineClass, но при этом вручную возникает ошибка Linkage. Что происходит здесь, что позволяет clojure делать это с помощью ловких лиц?