Есть ли возможность перезагрузить класс
От: Oval  
Дата: 09.03.04 17:26
Оценка:
Загруженый статическим методом class.forName
(перезагрузить надо прекомпилированный class-плагин)
Re: Есть ли возможность перезагрузить класс
От: Blazkowicz Россия  
Дата: 09.03.04 17:30
Оценка:
Здравствуйте, Oval, Вы писали:

O>Загруженый статическим методом class.forName

O>(перезагрузить надо прекомпилированный class-плагин)

Да. загружай его отдельным загрузчиком (Classloader). И forName делай с указанием конкретного загрузчика. Для обновления нужна создать новый загрузчик. И спросить класс у него. Он загрузит его заново.

В Яве 1.5 обещают более красивое решение.
Re[2]: Есть ли возможность перезагрузить класс
От: Oval  
Дата: 09.03.04 18:44
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, Oval, Вы писали:


O>>Загруженый статическим методом class.forName

O>>(перезагрузить надо прекомпилированный class-плагин)

B>Да. загружай его отдельным загрузчиком (Classloader). И forName делай с указанием конкретного загрузчика. Для обновления нужна создать новый загрузчик. И спросить класс у него. Он загрузит его заново.


B>В Яве 1.5 обещают более красивое решение.


Мысля вокруг этого и крутилась — не охота было проверять — тонну кода перелапачивать.
То есть практически в программе возможно существование разных классов но с одинаковыми именами?
Re: Есть ли возможность перезагрузить класс
От: dshe  
Дата: 10.03.04 07:01
Оценка:
Здравствуйте, Oval, Вы писали:

O>Загруженый статическим методом class.forName

O>(перезагрузить надо прекомпилированный class-плагин)

http://www.javaworld.com/javaqa/2002-07/01-qa-0705-loader-synch_p.html?

Q: I use the Class.forName() method to dynamically load Java classes. However, if I recompile a class and reload it, the new recompiled class does not load. How do I force class reloading?

A: The standard class loader will not reload a class for you. Instead, you need to develop a custom class loader. Luckily, such a class loader already exists, and I'm sure with a little alteration it will serve your needs.

First, download JUnit. Then look at its junit.runner.TestCaseClassLoader.java, a class loader able to reload any given class. JUnit uses TestCaseClassLoader so you do not need to shut down the test GUI (graphical user interface) every time you recompile your test classes. Unfortunately, the latest version cannot reload classes from jar files.

--
Дмитро
Re[3]: Есть ли возможность перезагрузить класс
От: Blazkowicz Россия  
Дата: 10.03.04 08:44
Оценка:
Здравствуйте, Oval, Вы писали:

O>Мысля вокруг этого и крутилась — не охота было проверять — тонну кода перелапачивать.

O>То есть практически в программе возможно существование разных классов но с одинаковыми именами?

Да. И что самое противное такая ситуация является потонцеальным источником различных ошибок. Особенно в таких бесплатных решениях как JBoss.

Я бы на твоём месте попытался построить решение на базе 1.5. Если, конечно есть возможность.
Re[4]: Есть ли возможность перезагрузить класс
От: dshe  
Дата: 10.03.04 09:05
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Я бы на твоём месте попытался построить решение на базе 1.5. Если, конечно есть возможность.


Я что-то сходу не нашел. Точно есть?
--
Дмитро
Re[5]: Есть ли возможность перезагрузить класс
От: Blazkowicz Россия  
Дата: 10.03.04 09:22
Оценка:
Здравствуйте, dshe, Вы писали:

D>Я что-то сходу не нашел. Точно есть?


А ты хорошо читал статьи, ссылки на которые давал?

http://java.sun.com/developer/technicalArticles/releases/j2se15/

Раздел:

New JVM profiling API (JSR-163)

Фича называется Instrumentation.

The new java.lang.instrument package provides services that allow Java programming agents to instrument programs running on the Java virtual machine. The intrumentation mechanism is modification of the bytecodes of methods.

Re[6]: Есть ли возможность перезагрузить класс
От: dshe  
Дата: 10.03.04 09:55
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Раздел:

B>New JVM profiling API (JSR-163)
B>Фича называется Instrumentation.

Что ж, готов согласиться, что это API может помочь в решении данной задачи. Спасибо за подсказку.
--
Дмитро
Re: Есть ли возможность перезагрузить класс
От: Аноним  
Дата: 10.03.04 09:58
Оценка:
Да, конечно, вспомни школу.
Re[7]: Есть ли возможность перезагрузить класс
От: fenix13  
Дата: 23.01.08 17:14
Оценка:
Привет ребята :

Я использую пример по данной вами ссылки выше .

И у меня ничего не выходит .
У меня постоянно такая ошибка redefineClasses is not supported in this environment

Что это может быть ?
Re[8]: Есть ли возможность перезагрузить класс
От: Blazkowicz Россия  
Дата: 23.01.08 18:34
Оценка:
Здравствуйте, fenix13, Вы писали:

F>У меня постоянно такая ошибка redefineClasses is not supported in this environment

Полнай текст ошибки + stacktrace. А так же используемая JVM, ОС, и как запускаешь.
Re[8]: Есть ли возможность перезагрузить класс
От: Blazkowicz Россия  
Дата: 23.01.08 18:35
Оценка:
Здравствуйте, fenix13, Вы писали:

F>У меня постоянно такая ошибка redefineClasses is not supported in this environment


http://download.java.net/jdk/jdk-api-localizations/jdk-api-zh-cn/builds/latest/html/en/api/java/lang/instrument/Instrumentation.html#isRedefineClassesSupported()
Re[8]: Есть ли возможность перезагрузить класс
От: dshe  
Дата: 24.01.08 07:15
Оценка:
Здравствуйте, fenix13, Вы писали:

F>Я использую пример по данной вами ссылки выше .


F>И у меня ничего не выходит .

F>У меня постоянно такая ошибка redefineClasses is not supported in this environment

На текущий момент в большинстве случаев я предпочел бы вариант с classloader'ами (не такой уж некрасивый этот вариант), а Instrumentation оставил бы для очень специфических случаев.
--
Дмитро
Re[9]: Есть ли возможность перезагрузить класс
От: fenix13  
Дата: 24.01.08 07:43
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Полнай текст ошибки + stacktrace. А так же используемая JVM, ОС, и как запускаешь.


OS: Windows XP Pro SP2
JVM: 1.6.0.04
IDE: Eclipse 3.4

Запускаю из еклипса след образом :
запускаю главный класс BCITest с параметром VM: -javaagent:D:/work/NewJVMProfilingAPI/lib/myBCI.jar

Этот myBCI.jar — я делал следующим образом :
скомпилил класс myBCI из примера — получил myBCI.class , сдела вручную MANIFEST.MF — со следующим контентом :
Manifest-Version: 1.0
Created-By: 1.6.0_04 (Sun Microsystems Inc.)
Premain-Class: myBCI

Дальше вручную сделал myBCI.jar файл : jar cfM myBCI.jar META-INF/MANIFEST.MF myBCI.class . Получил правельный джар.

Ошибка :
OriginalClass — это выполнение первой версии класс , она проходит нормально
java.lang.UnsupportedOperationException: redefineClasses is not supported in this environment

Если выполнять эту программу в консоли так как написано в примере то результатом будет :
OriginalClass

тоесть ошибки не выдает , или просто не пишет сюда .

Что это может быть ?
Спасибо,
Re[9]: Есть ли возможность перезагрузить класс
От: fenix13  
Дата: 24.01.08 07:48
Оценка:
Здравствуйте, dshe, Вы писали:

D>На текущий момент в большинстве случаев я предпочел бы вариант с classloader'ами (не такой уж некрасивый этот вариант), а Instrumentation оставил бы для очень специфических случаев.


Да это неплохой и рабочий вариант . Но сколько я не бился — он не позволяет подменить класс. Загрузить новый класс и работать с ним можно . Но это не то что мне нужно .

Если есть реализация примера с classloader'ами — которая подменяет классы то киньте мне . Интересно как сделано в Tomacat ? У них реализовано както что Сервлеты подгребаються автоматически без перезагрузки Tomcat .
Re[10]: Есть ли возможность перезагрузить класс
От: Blazkowicz Россия  
Дата: 24.01.08 08:04
Оценка:
Здравствуйте, fenix13, Вы писали:

F>скомпилил класс myBCI из примера — получил myBCI.class , сдела вручную MANIFEST.MF — со следующим контентом :

F>Manifest-Version: 1.0
F>Created-By: 1.6.0_04 (Sun Microsystems Inc.)
F>Premain-Class: myBCI

http://rsdn.ru/forum/message/2809283.1.aspx
Автор: Blazkowicz
Дата: 23.01.08
Re[10]: Есть ли возможность перезагрузить класс
От: dshe  
Дата: 24.01.08 09:15
Оценка:
Здравствуйте, fenix13, Вы писали:

F>Здравствуйте, dshe, Вы писали:


D>>На текущий момент в большинстве случаев я предпочел бы вариант с classloader'ами (не такой уж некрасивый этот вариант), а Instrumentation оставил бы для очень специфических случаев.


F>Да это неплохой и рабочий вариант . Но сколько я не бился — он не позволяет подменить класс. Загрузить новый класс и работать с ним можно . Но это не то что мне нужно .


С подменой класса есть некоторые нюансы, которые надо учитывать. Например, что делать с существующими экземплярами классов, если класс исчез, или в классе добавилось новое поле? Расширять? Каким значением тогда инициализировать? Что делать если в момент переопределения исполняется метод, который в новом классе отсутствует? или идет обращение в удаленному (или переименованному) полю?

Поэтому Instrumentation обладает ограниченными возможностями по переопределению классов (в частности, насколько я понял из javadoc, добавление, удаление и переименовывание полей и методов не допускаются; можно только менять тела методов). Вариант с classloader'ами в определенной степени разрешает данные вопросы поскольку допускает сосуществование старой и новой версии классов (загруженных разными класслоадерами).

F>Если есть реализация примера с classloader'ами — которая подменяет классы то киньте мне . Интересно как сделано в Tomacat ? У них реализовано както что Сервлеты подгребаються автоматически без перезагрузки Tomcat .


Каждое веб-приложение загружаются своим classloader'ом. Когда Tomcat обнаруживает, что нужно перегрузить некоторое приложение (например, если поменялся web.xml), то он останавливает загруженное (вызывает destroy у сервлетов, фильтров, session и servlet context listener'ов), загружает новым класслоадером новое приложение и заново его инициализирует, а о старом (с его класслоадером) забывает позволяя GC его собрать. С jsp та же история.
--
Дмитро
Re[11]: Есть ли возможность перезагрузить класс
От: fenix13  
Дата: 24.01.08 09:38
Оценка:
Здравствуйте, dshe, Вы писали:



D>С подменой класса есть некоторые нюансы, которые надо учитывать. Например, что делать с существующими экземплярами классов, если класс исчез, или в классе добавилось новое поле? Расширять? Каким значением тогда инициализировать? Что делать если в момент переопределения исполняется метод, который в новом классе отсутствует? или идет обращение в удаленному (или переименованному) полю?


Есть не спорю , но идея таки в том что я буду менять только тело методов .

D>Поэтому Instrumentation обладает ограниченными возможностями по переопределению классов (в частности, насколько я понял из javadoc, добавление, удаление и переименовывание полей и методов не допускаются; можно только менять тела методов). Вариант с classloader'ами в определенной степени разрешает данные вопросы поскольку допускает сосуществование старой и новой версии классов (загруженных разными класслоадерами).


F>>Если есть реализация примера с classloader'ами — которая подменяет классы то киньте мне . Интересно как сделано в Tomacat ? У них реализовано както что Сервлеты подгребаються автоматически без перезагрузки Tomcat .


D>Каждое веб-приложение загружаются своим classloader'ом. Когда Tomcat обнаруживает, что нужно перегрузить некоторое приложение (например, если поменялся web.xml), то он останавливает загруженное (вызывает destroy у сервлетов, фильтров, session и servlet context listener'ов), загружает новым класслоадером новое приложение и заново его инициализирует, а о старом (с его класслоадером) забывает позволяя GC его собрать. С jsp та же история.


Вот это, мне очень нравиться . Я по началу тоже пытался так сделать . Но не придумал как удалять старый клас лоадер . Если есть идеи поделитесь . И если например убить старый клас лоадер . То я так понимаю когда я загружу новый лоадер с новой версией класс . То когда понадобиться этот класс — то автоматически подгребётся новая версия класса .
Re[11]: Есть ли возможность перезагрузить класс
От: fenix13  
Дата: 24.01.08 09:45
Оценка:
Здравствуйте, Blazkowicz, Вы писали:


B>http://rsdn.ru/forum/message/2809283.1.aspx
Автор: Blazkowicz
Дата: 23.01.08


Намёк я понял и использовал его . По идеи в Манифесте нехватало Can-Redefine-Classes: true

Я поставил и функция isRedefineClassesSupported() — стала выдавать true . Незнаю или правду говорит или просто берет значение из манифеста . Может еще чего нужно конфигурировать в самом JVM ?

Появились новые проблемы (это происходит в момент вызова redefineClasses):

OriginalClass
Exception in thread "main" java.lang.NoClassDefFoundError: class names don't match
at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
at sun.instrument.InstrumentationImpl.redefineClasses(Unknown Source)
at BCITest.main(BCITest.java:28)


Значения я проверяю , валидные ему даю все нормально . Что еще может быть ?

Может этот пример очень сырой — его както дополнять нужно может ?
Re[12]: Есть ли возможность перезагрузить класс
От: fenix13  
Дата: 24.01.08 10:25
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

Ура!!!!!!!!! Я сделал . Радости нет придела и благодарности тоже , за оказанную помощ .

Короче это уже я затупил . У меня второй клас которым я хотел заменить созданный был в пакете . Получалось что имена не совпадали .

Большое спасибо !!!!!!.
Re[12]: Есть ли возможность перезагрузить класс
От: Blazkowicz Россия  
Дата: 24.01.08 10:42
Оценка: 1 (1)
Здравствуйте, fenix13, Вы писали:

F>Вот это, мне очень нравиться . Я по началу тоже пытался так сделать . Но не придумал как удалять старый клас лоадер . Если есть идеи поделитесь . И если например убить старый клас лоадер . То я так понимаю когда я загружу новый лоадер с новой версией класс . То когда понадобиться этот класс — то автоматически подгребётся новая версия класса .

Не надо удалять загрузчики. Надо контролировать потоки, так чтобы они шли через классы и их экземпляры исключительно нового загрузчика.
Re[11]: Есть ли возможность перезагрузить класс
От: fenix13  
Дата: 25.01.08 09:44
Оценка:
Здравствуйте, Blazkowicz

Появилась еще одна интересная задачя . Если есть идеи то подскажы . Сейчас обрисую :

Мне нужно перегрузить метод classloader . А именно чтобы с самого начала работы программы — она лезла в мой класслоадер а не в системный . Возможно ли такое сделать? Мне это нужно для того чтобы контролировать какую именно версию класса мне нужно загружать в момент работы программы .
Если есть вопросы или предложения , давай подискусируем .
Re[12]: Есть ли возможность перезагрузить класс
От: Blazkowicz Россия  
Дата: 25.01.08 09:52
Оценка: 1 (1)
Здравствуйте, fenix13, Вы писали:

F>Появилась еще одна интересная задачя . Если есть идеи то подскажы . Сейчас обрисую :

F>Мне нужно перегрузить метод classloader . А именно чтобы с самого начала работы программы — она лезла в мой класслоадер а не в системный . Возможно ли такое сделать? Мне это нужно для того чтобы контролировать какую именно версию класса мне нужно загружать в момент работы программы .
F>Если есть вопросы или предложения , давай подискусируем .

Да, проще простого. Все твои классы нужно сделать недоступным для класслоадера который обычно их загружеает. Затем в коде создать экземпляр своего класслоадера, научить его искать твои классы, и далее все обращения вести через него. Там уже надо смотреть по ситуации и окружению. Thread.setContextClassloader(), либо просто загрузить класс своим класслоадером, а этот класс уже будет подтягивать зависимости только через этот же класслоадер. В общем штудируй API к классам ClassLoader/URLClassLoader, смотри исходный код этих классов и все у тебя получится.
Re[12]: Есть ли возможность перезагрузить класс
От: dshe  
Дата: 25.01.08 10:15
Оценка: 7 (1)
Здравствуйте, fenix13, Вы писали:

F>Здравствуйте, Blazkowicz


F>Появилась еще одна интересная задачя . Если есть идеи то подскажы . Сейчас обрисую :


F>Мне нужно перегрузить метод classloader . А именно чтобы с самого начала работы программы — она лезла в мой класслоадер а не в системный . Возможно ли такое сделать? Мне это нужно для того чтобы контролировать какую именно версию класса мне нужно загружать в момент работы программы .

F>Если есть вопросы или предложения , давай подискусируем .

Возможно тебе поможет свойство java.system.class.loader подменить системный класслоадер. Параметром является имя класса класслоадера, который должен иметь конструктор с одном параметром, принимающим родительский класслоадер. Например,
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

public class My extends URLClassLoader {

    public My(ClassLoader parent) throws Exception {
        super(new URL[] { new File("./classes").toURL() }, parent);
    }
}

запуск
java -Djava.system.class.loader=My Main


Для полноты картины пусть Main класс выводит цепочку класслоадеров
public class Main {
    public static void main(String[] args) {
        for (ClassLoader loader = Main.class.getClassLoader(); loader != null; loader = loader.getParent()) {
            System.out.print(loader == ClassLoader.getSystemClassLoader() ? "system " : "       ");
            System.out.println(loader);
        }
    }
}


Тогда с подмененным класслоадером цепочка выглядит так
system My@42e816
       sun.misc.Launcher$AppClassLoader@7d772e
       sun.misc.Launcher$ExtClassLoader@11b86e7

А со стандартным
system sun.misc.Launcher$AppClassLoader@d9f9c3
       sun.misc.Launcher$ExtClassLoader@9cab16

Т.е. свой класслоадер загружается стандартным системным (AppClassLoader) и он же передается в качестве родительского.
--
Дмитро
Re[13]: Есть ли возможность перезагрузить класс
От: fenix13  
Дата: 25.01.08 11:10
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Да, проще простого. Все твои классы нужно сделать недоступным для класслоадера который обычно их загружеает. Затем в коде создать экземпляр своего класслоадера, научить его искать твои классы, и далее все обращения вести через него. Там уже надо смотреть по ситуации и окружению. Thread.setContextClassloader(), либо просто загрузить класс своим класслоадером, а этот класс уже будет подтягивать зависимости только через этот же класслоадер. В общем штудируй API к классам ClassLoader/URLClassLoader, смотри исходный код этих классов и все у тебя получится.


Ты меня натолкнул вобще на сногсшибательную идею : я только что сделал тестовую прогу которая в самом начале — просто напросто копирует либы из моего дочернего сервера в дерикторию класпаза — таким образом либы просто подменяются — и когда происходит загрузка обьекта — он уже все танет с новых либ .

Это работает 100%

Что ты думаешь по этому поводу ? насколько это безопасный вариант ?
Re[14]: Есть ли возможность перезагрузить класс
От: Blazkowicz Россия  
Дата: 25.01.08 11:24
Оценка:
Здравствуйте, fenix13, Вы писали:

F>Ты меня натолкнул вобще на сногсшибательную идею : я только что сделал тестовую прогу которая в самом начале — просто напросто копирует либы из моего дочернего сервера в дерикторию класпаза — таким образом либы просто подменяются — и когда происходит загрузка обьекта — он уже все танет с новых либ .

Понимаешь ли в чем дело. Я понятия не имею кто такой дочерний сервер, что да дирекотрия класпаза и в каком контектсе работает твое приложение вообще. Standalone, J2EE, Spring, Eclipse RCP.

F>Это работает 100%

Не ясно зачем копировать либы со старта, если их можно вообще не помещать куда не надо. Есть ещё такая бага под виндой, что когда URLClassLoader загружает класс из jar, то jar лочится файловой системой.

F>Что ты думаешь по этому поводу ? насколько это безопасный вариант ?

На безопасный вариант не похоже, а так ХЗ, что там за приложение на этим скрывается.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.