2014-12-24 2 views
0

== Предыстория == Я пытаюсь реализовать функцию автоматического обновления для приложения java для рабочего стола, которое предназначено для использования своего рода супервизора, который может решить где загружать приложение (т. е. мы пытаемся загрузить новую версию или не отставать от текущего). Для этой цели я создал загрузчик, который использует URLClassLoader.URLClassLoader не может выполнять запросы на загрузку класса, исходящие из новых потоков

== Ситуация == я следующие артефакты:.

  • bootstrapper.jar
  • app.jar
  • Библиотека/* баночка

bootstrapper.jar имеет собственный метод main(), а точка входа в файл файла MANIFEST -

Main-Class: ru.skarpushin.projects.bootstrapper.Bootstrapper 

Так что я могу работать, что путем вызова командной строки

javaw -jar bootsrapper.jar 

app.jar это основное приложение (Spring-приложение) с числом зависимостей на 3-й партии LIBS (находится в Lib . папки) и ссылки из manifest.mf

Class-Path: lib/balloontip-1.2.3-SNAPSHOT.jar lib/commons-codec-1.6.ja 
r lib/commons-lang3-3.1.jar lib/commons-logging-1.1.1.jar lib/fluent- 
hc-4.2.1.jar lib/gson-2.2.2.jar lib/guava-11.0.2.jar lib/log4j-1.2.16 
.jar lib/org.springframework.asm-3.1.2.RELEASE.jar lib/org.springfram 

Библиотека/* баночка - куча зависимостей

== То, как загрузчиков классов пользователей I является ==

classLoader = new URLClassLoader(new URL[] { new File("app.jar").toURI().toURL() }, Thread.currentThread() 
     .getContextClassLoader()); 
Thread.currentThread().setContextClassLoader(classLoader); 
Class entryPointClass = classLoader.loadClass(entryPoint); 
Method mainMethod = entryPointClass.getMethod("main", String[].class); 
mainMethod.invoke(null, (Object) args); 

== Проблема == Это отлично работает для некоторых классов и не для других. Вопрос в том, почему и как это исправить?

Похоже, что это как-то связано с потоками. Давайте назовем Thread1 - основной поток, когда приложение запускается и где я создаю URLCalssLoader. Все запросы на загрузку классов в Thread1 успешно выполнялись независимо от их местоположения (будь то app.jar или из libs). Все запросы на загрузку классов во вновь созданных потоках (назовем их ThreadN) не удались.

Интересная вещь, которую я обнаружил, что: - скажем ThreadN не удается загрузить CLASSA - Если изменить код так, что ClassA будет вынужден загрузить из thread1 - тогда не будет ошибок нет на ThreadN - я проверил - context classloader Thread1 и ThreadN - одинаковые

Так что это похоже на ThreadN. Я могу использовать кешированные классы, но не могу загружать новые классы.

Любые мысли, чтобы исправить это?

+0

«Я пытаюсь реализовать функцию автоматического обновления для приложения java для рабочего стола» - я думаю, что веб-сайт java - это то, что вы ищете? – slowy

+0

Я не рассматриваю возможность рассмотрения и оценки вариантов. WebStart - это совсем другая история, мой вопрос НЕ связан с этим. Но спасибо за предложение. –

ответ

0

К сожалению, это был мой код, вызывающий такое поведение.

Bootstrapper.был запущен метод main(); он открыл URLClassLoader, загрузил точку входа приложения и вызвал ее. Все, что сделано в основной теме. Дело в том, что это приложение для рабочего стола java - и как только отображается основной кадр, тогда код разблокируется, и вызывается метод bootstrapper.main (пока приложение все еще выполняется).

BUT in bootstrapper.main У меня есть предложение finally, где я явно вызываю метод .close() на URLClassLoader, который заставляет его использовать только кешированные классы и не загружать новые классы.

} finally { 
    try { 
     classLoader.close(); 
    } catch (IOException e) { 
     // failed to close. don't care. Should we? 
    } 
} 

Как только я удалил этот код, проблема исчезла.

Смежные вопросы