Вопрос по JavaSE classloading
можно генерить при загрузке проксю (например, на Groovy) к классу настроек
Проблема в том, что приходится работать через reflection, и вызовы методов становятся громоздкими. Как нибудь можно это исправить?Не понял только одного, почему ты Object потом не приводишь к Singleton? В твоём примере это будет работать.
Не понял только одного, почему ты Object потом не приводишь к Singleton? В твоём примере это будет работать.Я пробовал, не прокатывает. Singleton.name начинают перекрываться. Но я на всякий случай завтра еще раз проверю.
хренасе заморочкаВроде по другому никак не сделать.
можно генерить при загрузке проксю (например, на Groovy) к классу настроекТогда же ведь придется декомпилировать и править код клиентской библиотеки? Я не буду этого делать, потому что имеющееся решение с рефлекшеном лучше.
Представь, что Singleton и SingletonUser (это как раз и есть аналог моей закрытой библиотеки) ты не можешь менять, а можешь менять только Test. И в Test тебе надо создать несколько потоков и SingletonUser в каждом и вызывать в них методы SingletonUser, чтобы они не мешали друг другу(а мешают они потому что все обращаются к static полю класса Singleton)
Я пробовал, не прокатывает. Singleton.name начинают перекрываться. Но я на всякий случай завтра еще раз проверю.типа кастинг приводит к конкретизации класслоадера
Я пробовал, не прокатывает. Singleton.name начинают перекрываться. Но я на всякий случай завтра еще раз проверю.Понятно. Сначала я не заметил static. Обычно singleton содержит только одно статическое поле (себя) и имеет private конструктор. Как раз для рефакторинга под нужды, подобные твоим.
Я собрал твой пример, и вызвал getSingletonName через reflection. У меня получилось, что строка общая для обоих классов.
добавь assert cls1 != cls2
видимо, URL неверный указал и классы дефолтным (parent) класс-лоадером загрузилисьТак и есть. Я без понятия, что там надо ей указать, чтобы она загрузила разные.
Проблема в том, что приходится работать через reflection, и вызовы методов становятся громоздкими. Как нибудь можно это исправить?Подобная проблема часто решается при поддержке различных плагинов, которые загружаются внутри с использованием своих ClassLoader's. И решение там - базовый интерфейс, реализуемый соответствующими плагинами (сущностями). После создания объекта, его тип приводится к интерфейсу плагина и вся дальнейшая работа выполняется уже с этим интерфейсом.
package classloading;
public interface SingletonInterface {
public String getSingletonName;
public void setSingletonName(String name);
}
public class SingletonUser implements SingletonInterface {
// implementation skipped
}
package classloading;
import java.net.URL;
import java.net.URLClassLoader;
public class Test {
public static void main(String[] args) throws Exception {
URL[] urlsToLoadFrom = new URL[] { new URL("file:subdir/") };
URLClassLoader loader1 = new URLClassLoader(urlsToLoadFrom);
URLClassLoader loader2 = new URLClassLoader(urlsToLoadFrom);
Class cls1 = Class.forName("classloading.SingletonUser", true, loader1);
Class cls2 = Class.forName("classloading.SingletonUser", true, loader2);
SingletonInterface su1 = (SingletonInterface) cls1.newInstance;
SingletonInterface su2 = (SingletonInterface) cls2.newInstance;
su1.setSingletonName("111111");
su2.setSingletonName("222222");
System.out.println(su1.getSingletonName;
System.out.println(su2.getSingletonName;
}
}
В данном случае SingletonInterface должен грузиться тем же classloader'ом, что и Test (например, быть в classpath). SingletonUser и Singleton - наоборот, должны грузиться отдельными classloader'ами (точно так же, как в исходном примере).
*** ~/jtest/loading $ ls classloading/*.class
classloading/SingletonInterface.class classloading/Test.class
*** ~/jtest/loading $ ls subdir/classloading/*.class
subdir/classloading/Singleton.class subdir/classloading/SingletonUser.class
Оставить комментарий
Gaishnik
У меня есть закрытый проприетарный клиент для некоторого application сервера, который хранит настройки подключения в static полях некоторого класса. Из-за этого параллельная работа с разными серверами в несколько потоков становится невозможной. Я пытаюсь решить проблему, загружая копии всех классов отдельно для каждого сервера.Общая схема примерно такая
В результате мы имеем 2 разные копии Singleton, и, соответственно, Singleton.name
Проблема в том, что приходится работать через reflection, и вызовы методов становятся громоздкими. Как нибудь можно это исправить?