Проблемы с Java при перезагрузке кода с использованием ClassLoader - PullRequest
4 голосов
/ 21 июня 2010

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

Используя ClassLoader, я смог изменить локальную переменную с Class MyVar1 на Class MyVar2 во время выполнения, используя код http://www.exampledepot.com/egs/java.lang/reloadclass.html,, но мне не удалось заменить этот Class 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 ]

1 голос
/ 21 июня 2010

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

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

1 голос
/ 21 июня 2010

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

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

(Использование java.net.URLClassLoader.newInstance, вероятно, проще при создании собственной реализации загрузчика классов.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...