Почему мой класс не перезагружается? - PullRequest
0 голосов
/ 25 декабря 2009

Я знаю, что мне не хватает чего-то простого. Я пытаюсь динамически скомпилировать класс, а затем перезагрузить его после изменения. Следующий код работает. Однако, когда я вызываю его дважды (один раз после изменения .java), определение класса не обновляется. Чего мне не хватает?

File file = new File("/eraseme/Eraseme.java");
File[] files = new File[] {file};
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();           
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(files);
CompilationTask task = compiler.getTask(null, fileManager, null, null,null,compilationUnits);
boolean madeIt = task.call(); // works

File classFile = new File("/eraseme/Eraseme.class");
URL url = classFile.toURL();
URL[] urls = new URL[] { url };
ClassLoader cl = new URLClassLoader(urls);      
Class cls = cl.loadClass("Eraseme");
TestApi test = (TestApi) cls.newInstance();
System.out.println(test.getVersion());

1 Ответ

2 голосов
/ 25 декабря 2009

Что вам не хватает, так это то, что URL-адреса, переданные в URLClassLoader, должны быть каталогами, которые затем ищутся. Происходит то, что создаваемый вами URLClassLoader на самом деле не находит файл .class, но не может найти класс и возвращается к тому, что родительский загрузчик классов загружает класс.

В частности, попробуйте изменить второй бит вашего кода так:

File classFile = new File("/eraseme");
URL url = classFile.toURL();
URL[] urls = new URL[] { url };
ClassLoader cl = new URLClassLoader(urls);      
Class cls = cl.loadClass("Eraseme");  // will try to load /eraseme/Eraseme.class
TestApi test = (TestApi) cls.newInstance();
System.out.println(test.getVersion());

Обратите внимание, что если ваш класс вызывается (с пакетом) com.mycompany.erasestuff.EraseMe, загрузчик классов будет искать в файле /eraseme/com/mycompany/erasestuff/EraseMe.class

Обратите внимание, что когда вы делаете это, вы не хотите, чтобы системный загрузчик классов мог загружать класс EraseMe. Системный загрузчик классов будет иметь приоритет, и ваш URLClassloader ничего не загрузит. (К сожалению, когда вы говорите загрузчику классов «загрузить этот класс», он first проверяет, может ли его родительский загрузчик классов загрузить класс, затем он пытается загрузить его сам. Если системный загрузчик классов может загрузить этот класс, вы никогда не получите другую версию)

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