Что делает горячее развертывание «трудной проблемой»?

На работе у нас возникли проблемы с исключениями из « PermGen out of memory », и руководство команды решило, что это ошибка в JVM – что-то связанное с горячим развертыванием кода. Не объясняя много деталей, он отметил, что горячее развертывание – это «трудная проблема», настолько сложная, что даже .NET этого еще не делает.

Я нашел много статей, объясняющих горячее развертывание с высоты птичьего полета, но всегда не имеющих технических деталей. Может ли кто-нибудь указать мне на техническое объяснение и объяснить, почему горячее развертывание является «трудной проблемой»?

4 Solutions collect form web for “Что делает горячее развертывание «трудной проблемой»?”

Когда class загружается, различные статические данные о classе хранятся в PermGen. Пока существует живая ссылка на этот экземпляр classа, экземпляр classа не может быть собран в мусор.

Я считаю, что часть проблемы связана с тем, должен ли GC удалять старые экземпляры classа из perm gen или нет. Как правило, каждый раз, когда вы горячо развертываете, в пул памяти PermGen добавляются экземпляры нового classа, а старые, которые теперь не используются, обычно не удаляются. По умолчанию Sun JVM не будут запускать сборку мусора в PermGen, но это может быть включено с дополнительными аргументами команды «java».

Поэтому, если вы быстро развернете достаточно времени, вы в конечном итоге исчерпаете пространство PermGen.

Если ваше веб-приложение не закрывается полностью, когда оно не развернуто – если оно, например, покидает stream, то все экземпляры classа, используемые этим веб-приложением, будут закреплены в пространстве PermGen. Вы передислоцируете и теперь имеете еще одну целую копию всех этих экземпляров classа, загруженных в PermGen. Вы отказываетесь от развертывания, и stream продолжает двигаться, закрепляя ДРУГОЙ набор экземпляров classа в PermGen. Вы передислоцируете и загружаете весь набор готовых копий … и в конечном итоге ваш PermGen заполняется.

Иногда вы можете исправить это:

  • Предоставление аргументов команды недавней Sun JVM для включения GC в PermGen и classов. Это: -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
  • Использование другой JVM, которая не использует фиксированный размер PermGen или что GC на загруженных classах

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

Даже это не обязательно устранит проблему из-за утечек загрузчика classа. (В некоторых случаях слишком много интернированных строк).

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

  • Утечка загрузчика classа: страшное исключение «java.lang.OutOfMemoryError: PermGen space»
  • Неизвестное поколение: Пермь
  • Представление постоянного поколения
  • Tomcat Wiki: как справиться с ошибками памяти

Проблема в общих чертах – это модель безопасности Java, которая на самом деле пытается предотвратить перезагрузку уже загруженного classа.

Конечно, Java с самого начала поддерживала динамическую загрузку classов, что сложно – это перезагрузка classа.

Было сочтено вредным (и по уважительной причине), что запущенное приложение java было введено новым classом с вредоносным кодом. Например, java.lang.String взломал реализацию, исходящую из Интернета, вместо того, чтобы создавать строку, удаляет некоторый случайный файл hile, вызывающий метод length ().

Итак, они задумали Java, и я предполагаю, что .NET CLR в результате, потому что он был очень «вдохновлен» в JVM) заключался в том, чтобы предотвратить загрузку уже загруженного classа снова той же виртуальной машины.

Они предложили механизм для переопределения этой «функции». Classloaders, но опять же правила для загрузчиков classов были, они должны спросить разрешение «родительского» загрузчика classов перед попыткой загрузить новый class, если родитель уже загрузил class, новый class игнорируется.

Например, я использовал загрузчики classов, которые загружают classы из LDAP или RDBMS

Горячее развертывание становится необходимостью в мире Java, когда сервер приложений становится основным для Java EE (а также создает потребность в микроконтейнерах, таких как весна, чтобы избежать такого рода бремени).

Перезапуск всего сервера приложений после каждого компилятора приводит к тому, что любой сумасшедший.

Таким образом, поставщик приложений, предлагающий этот «пользовательский» загрузчик classов для быстрого развертывания и использования конфигурационного файла, это поведение, СЛЕДУЕТ быть отключенным при установке в процессе производства. Но компромисс заключается в том, что вы должны использовать тонны памяти в процессе разработки. Таким образом, хороший способ сделать это – перезапустить каждые 3 – 4 развертывания.

Это не происходит с другими языками, которые были разработаны с самого начала для загрузки их classов.

Например, в Ruby вы можете добавлять методы к запущенному classу, переопределять метод во время выполнения или даже добавлять один метод к уникальному определенному объекту.

Компромисс в таких средах – это, конечно, память и скорость.

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ

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

Это JavaRebel от ZeroTurnaround

Sun JVM имеет фиксированное пространство PermGen, и в конечном итоге все это потребляется (да, по-видимому, из-за ошибки в коде, связанной с загрузкой classов) => OOM.

Если вы можете использовать JVM другого вендора (например, Weblogic one), он динамически расширяет пространство PermGen, поэтому вы никогда не получите OOM с привязкой к переносу.

Какую версию java вы используете? Были ошибки в раннем Sun 1.4.2, но он работает долгое время.
Кстати, как вы можете разделить новости с командой? Вы руководите командой?

  • Переопределить Java System.currentTimeMillis для проверки кода с временным кодом
  • Какова стандартная кодировка JVM?
  • Что делает -XX: MaxPermSize?
  • Java VM: воспроизводимый SIGSEGV на 1.6.0_17 и 1.6.0_18, как сообщить?
  • добавить параметры jvm в tomcat
  • Как узнать, какое хранилище использует моя JVM?
  • Шрифт недоступен для JVM с отчетами Jasper
  • JFrame.dispose () vs System.exit ()
  • Как получить аргументы vm из java-приложения?
  • В чем разница между JVM, JDK, JRE и OpenJDK?
  • Получение версии Java во время выполнения
  • Interesting Posts

    RealmChangeListener не вызывается, когда Realm обновляется в NotificationListenerService

    Избегайте блокировки компаниями электронной почты для массового / массового рассылки электронной почты?

    Конвертировать Mp4 в Mp3 с миниатюрой

    Переопределение переменных-членов в Java

    allowDefinition = ‘MachineToApplication’ при публикации из VS2010 (но только после предыдущей сборки)

    Как включить родительский контроль в конкретной учетной записи пользователя в Windows 7?

    Невозможно установить значение поля статического объекта (ошибка LNK2001: неразрешенный внешний символ)

    Как копировать файлы с поцарапанного CD / DVD?

    У большинства передних и задних USB-соединений обеспечивается одинаковая мощность и производительность?

    Как определить, находится ли точка в правой или левой части строки

    MongoDB, удалять объект из массива

    Определение частоты процессора (на kernel, на процессор)

    psql: не удалось подключиться к серверу: нет такого файла или каталога (Mac OS X)

    оператор виртуального присваивания C ++

    Как я могу поменять цвета с помощью GIMP?

    Давайте будем гением компьютера.