Проблемы с Java при перезагрузке кода с использованием ClassLoader

Я недавно сделал пост Обновление Java-кода во время выполнения и после нескольких часов, возясь с различными примерами кодов и читая учебники, я столкнулся со следующей проблемой:

С помощью ClassLoader я смог изменить локальную переменную из класса MyVar1 к классу MyVar2 во время выполнения, используя код на http://www.exampledepot.com/egs/java.lang/reloadclass.html, но я не смог заменить этот класс MyVar2 с другой версией MyVar2,

И то и другое MyVar1 а также MyVar2 реализовать интерфейс VarInterface, Основной класс содержит экземпляр переменной, используя тип VarInterface,

Я прочитал несколько других реализаций, которые утверждают, что они верны, но я не могу заставить это работать. Кто-нибудь может увидеть, что я здесь делаю не так?

Цикл основного класса:

    while(true){  
        i++;  
        Thread.sleep(1000);  
        ui.ping();  
        if(i > 3)  
            replaceVar();  
    }

replaceVar:

ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
    MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
    Class newClass = classLoader.loadClass("MyVar2");
    ui = (VarInterface)newClass.newInstance();

MyClassLoader.loadClass:

public Class<?> loadClass(String what){
    // Get the directory (URL) of the reloadable class
    URL[] urls = null;
    try {
        // Convert the file object to a URL
        File dir = new File(System.getProperty("user.dir")
                +File.separator+"dir"+File.separator);
        URL url = dir.toURL();
        urls = new URL[]{url};
    } catch (MalformedURLException e) {
    }

    // Create a new class loader with the directory
    ClassLoader cl = new URLClassLoader(urls);

    // Load in the class
    Class cls = null;
    try {
        cls = cl.loadClass("MyVar2");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

    return cls;
}

Для первых 3 итераций MyVar1.ping() называется, после этого MyVar2.ping() называется до бесконечности, даже если я заменю MyVar2.class а также MyVar2.java файлы.

2 ответа

Мне удалось решить проблему. Я забыл держать файлы вне пути к классам, что заставило ClassLoader читать новый экземпляр, только если он был другого класса, реализующего тот же интерфейс, а не когда я заменил класс другой версией.

Итак, в основном: проблема решена путем удаления файлов из проекта и их внешнего редактирования.

Я предполагаю, что вы используете два загрузчика классов. Во-первых, загрузчик системного класса, в котором содержится большая часть вашего кода. Ваш пользовательский загрузчик классов использует системный загрузчик классов в качестве родителя. Вы пытаетесь заставить пользовательский загрузчик классов заменить класс в системном загрузчике классов. Фактически, загрузчик пользовательских классов делегирует родителю предпочтение загрузки своих собственных классов.

Вам нужно убедиться, что загрузчик системного класса не загружает реализацию класса. Создайте загрузчик класса, который загружает реализацию класса и делегирует загрузчику класса системы. Для изменения реализации создайте еще один экземпляр загрузчика классов.

(С помощью java.net.URLClassLoader.newInstance Возможно, проще создать собственную реализацию загрузчика классов.)

Другие вопросы по тегам