Неужели нет способа выгружать или перезагружать классы во время выполнения в java? [Дубликат]

В веб-приложении каждая задача выполняется в виде запроса и ответа.

Программирование на стороне клиента - это HTML-код с Java-скриптом и его фреймворками, библиотеки выполняются в Internet Explorer, Mozilla, Chrome-браузерах. В сценарии Java-сценария серверные сервлеты программирования выполняются в Tomcat, web-логике, j боссе, WebSphere severs

153
задан Alex Miller 29 September 2008 в 15:17
поделиться

7 ответов

Единственный способ, которым может быть выгружен класс, - это использование класса Loadload для сбора мусора. Это означает, что ссылки на каждый отдельный класс и сам загрузчик классов должны идти по пути dodo.

Одним из возможных решений вашей проблемы является наличие Classloader для каждого файла jar и Classloader для каждого AppServers, который делегирует фактическую загрузку классов конкретным загрузчикам классов Jar. Таким образом, вы можете указать разные версии файла jar для каждого сервера приложений.

Это, однако, не тривиально. Платформа OSGi стремится сделать именно это, поскольку каждый комплект имеет другой загрузчик классов, а зависимости решаются платформой. Может быть, хорошим решением было бы взглянуть на него.

Если вы не хотите использовать OSGI, одной из возможных реализаций может быть использование одного экземпляра класса JarClassloader для каждый файл JAR.

И создайте новый класс MultiClassloader, расширяющий Classloader. Этот класс внутренне имел бы массив (или список) JarClassloaders, а в методе defineClass () выполнял бы итерацию по всем внутренним загрузчикам классов до тех пор, пока не будет найдено определение или исключение NoClassDefFoundException. Для добавления новых классов JarClassloaders в класс может быть предоставлено несколько методов доступа. Существует несколько возможных реализаций в сети для MultiClassLoader, поэтому вам даже не нужно писать свои собственные.

Если вы инициируете MultiClassloader для каждого подключения к серверу, в принципе, возможно, что каждый сервер использует другую версию того же класса.

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

174
ответ дан RevanthKrishnaKumar V. 28 August 2018 в 00:21
поделиться
  • 1
    Также обратите внимание, что согласно java.sun.com/docs/books/jls/second_edition/html/… разгрузка классов является оптимизацией и, в зависимости от реализации JVM, может или не может произойти , – Dan 18 February 2010 в 12:50
  • 2
    В качестве более простой и легкой альтернативы OSGi, попробуйте JBoss Modules - модульную загрузку классов с загрузчиком классов для каждого модуля (группа баннеров). – Ondra Žižka 26 June 2013 в 19:35

Если вы живете, если класс разгрузки работал в JConsole или что-то еще, попробуйте добавить java.lang.System.gc() в конец логики разгрузки вашего класса. Он явно запускает сборщик мусора.

0
ответ дан Aleksander Drozd 28 August 2018 в 00:21
поделиться
  • 1
    Осторожно: System.gc () не требует вызова GC. Он только просит jvm запустить его, но он не применяет его. И IME часто не запускает GC: - \ – Juh_ 12 January 2018 в 09:23

Да, есть способы загрузить классы и «разгрузить» их позже. Хитрость заключается в том, чтобы реализовать свой собственный загрузчик классов, который находится между загрузчиком класса высокого уровня (загрузчик класса System) и загрузчиками классов серверов приложений, и надеяться, что загрузчики классов сервера приложений делегируют загрузку классов в верхние загрузчики .

Класс определяется его пакетом, его именем и загружаемым им загрузчиком классов. Запрограммируйте загрузчик классов «прокси», который является первым, который загружается при запуске JVM. Рабочий процесс:

  • Программа запускается, и настоящий «основной» класс загружается этим прокси-загрузчиком классов.
  • Каждый класс, который затем обычно загружается (т. Е. Не через другой загрузчик классов реализация, которая могла бы разрушить иерархию) будет делегирована этому загрузчику классов.
  • Прокси-загрузчик классов делегирует java.x и sun.x системному загрузчику классов (эти не должны загружаться через любой другой загрузчик классов, чем системный загрузчик классов).
  • Для каждого заменяемого класса создайте экземпляр класса loadload (который действительно загружает класс и не передает его родительскому загрузчику классов) и загружает его через это.
  • Сохраните пакет / имя классов как ключи и загрузчик классов как значения в структуре данных (например, Hashmap).
  • Каждый раз, когда прокси-загрузчик классов получает запрос для класса, который был прежде чем он возвращает класс из загрузчика классов, хранящегося ранее.
  • Достаточно найти массив байтов класса загрузчиком класса ( или «удалить» пару ключ / значение из вашей структуры данных) и перезагрузить класс, если вы хотите его изменить.

Выполнено прямо там не должно быть ClassCastException или LinkageError и т. д.

Для получения дополнительной информации о иерархиях загрузчика классов (да, это именно то, что вы здесь реализуете;) смотрите «Сервер Java Programming "Теда Ньюварда - эта книга помогла мне реализовать что-то очень похожее на то, что вы хотите.

37
ответ дан ArtB 28 August 2018 в 00:21
поделиться
  • 1
    Я не понимаю людей, которые отметили -1 для ответа, не оставив комментария. Для меня хорошо выглядит. Возможно, наличие одного ClassLoader для каждого класса слишком много, один ClassLoader на JAR имеет смысл. Может быть более конкретным о том, как принудительно загрузить класс в предлагаемой схеме? Например. как я могу гарантировать, что экземпляры классов, загружаемых ClassLoaderA, не передаются экземплярами, загружаемыми ClassLoaderB? – dma_k 20 January 2011 в 01:23
  • 2
    @dma_k точно, ответ хороший, но он не касается ключевых моментов, которые вы упомянули. – zinking 21 October 2013 в 11:03
  • 3
    @Georgi есть ли существующая реализация, которую мы можем внедрить / использовать для этого? – ArtB 2 August 2017 в 14:20
  • 4
    Было бы очень полезно, если бы вы могли предоставить образец Java-кода. Чтобы быть точным, я ищу, как разгрузить классы с помощью CustomClassLoader, но не повезло. – Sriharsha g.r.v 13 December 2017 в 14:59
  • 5
    @ Sriharshag.r.v Вы пробовали это и внедрили образец? – niaomingjian 2 March 2018 в 02:57

Вы можете выгрузить ClassLoader, но вы не можете выгружать определенные классы. Более конкретно, вы не можете выгружать классы, созданные в ClassLoader, который не находится под вашим контролем.

Если возможно, я предлагаю использовать свой собственный ClassLoader, чтобы вы могли его выгружать.

6
ответ дан Jason Cohen 28 August 2018 в 00:21
поделиться

Я написал пользовательский загрузчик классов, из которого можно разгрузить отдельные классы без GCing загрузчика классов. Jar Class Loader

14
ответ дан Kamran 28 August 2018 в 00:21
поделиться
  • 1
    Работает как шарм :). Есть ли способ выгрузить все файлы классов файла jar? – Ercksen 13 October 2015 в 11:35
  • 2
    К сожалению, на данный момент. Но посмотрим на это. Может быть в будущих выпусках. – Kamran 30 November 2015 в 18:42
  • 3
    Кстати, я нашел небольшое обходное решение. Если у вас есть один файл JarClassLoader для каждого загруженного файла jar, вы можете называть его getLoadedClasses(), затем перебирать его и выгружать. – Ercksen 30 November 2015 в 18:54

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

Большинство людей, которым необходимо выполнить этот тип предмет в конечном итоге используя OSGi . OSGi действительно мощный и удивительно легкий и простой в использовании,

12
ответ дан Steve g 28 August 2018 в 00:21
поделиться

Классы имеют скрытую ссылку на экземпляр ClassLoader и наоборот. Они собирают мусор, как с объектами Java. Не удаляя интерфейс инструмента или аналогичный, вы не можете удалить отдельные классы.

Как всегда вы можете получить утечки памяти. Любая сильная ссылка на один из ваших классов или загрузчик классов будет утечка всего. Это происходит, например, с реализациями Sun ThreadLocal, java.sql.DriverManager и java.beans.

4
ответ дан Tom Hawtin - tackline 28 August 2018 в 00:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: