Пять секретов... флагов командной строки JVM

Тонкая настройка производительности JVM и среды исполнения Java

У виртуальных машин Java™ сотни параметров командной строки, которые опытные Java-разработчики могут использовать для настройки среды исполнения Java. Эта статья учит контролировать и регистрировать производительность компилятора, отключать прямой сбор мусора (System.gc();), расширять JRE и др.

Тед Ньюворд, директор, Neward & Associates

Тед Ньюворд (Ted Neward) является директором компании “Neward & Associates”. Он занимается консультированием, преподаванием и презентациями продуктов на основе Java, .NET, XML-сервисов и других платформ. В настоящее время он живет недалеко от Сиэттла, штат Вашингтон.



26.10.2012

Об этом цикле статей

Вы думаете, что знаете о Java-программировании все? На самом деле большинство разработчиков только скребет по поверхности платформы Java, изучив ее лишь настолько, чтобы выполнять свою работу. В этом цикле статей Тед Ньюард углубляется в функциональные возможности платформы Java, выявляя малоизвестные факты, которые могут помочь в решении самых заковыристых задач программирования.

JVM ― рабочая лошадка, которая обеспечивает функциональность и производительность Java-приложений и которую большинство Java-разработчиков принимает как должное. И очень немногие действительно понимают, как JVM делает то, что она делает — такие вещи, как распределение объектов и сбор мусора, развертывание потоков, открытие и закрытие файлов, интерпретация и/или JIT-компиляция байт-кода Java и многое другое.

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

Эта статья из цикла Пять секретов знакомит читателей с несколькими флагами командной строки JVM, которые можно использовать для диагностики и настройки производительности виртуальной машины Java.

1. DisableExplicitGC

Развить навыки по этой теме

Этот материал — часть knowledge path для развития ваших навыков. Смотри Стать Java-программистом

Я не могу сказать, сколько раз, когда меня просили проконсультировать по проблеме производительности приложений, быстрый grep по коду показывал то, что приведено в листинге 1 — классическую антимодель производительности Java.

Листинг 1. System.gc();
// Мы только что выпустили кучу объектов, так что пусть 
// сборщик мусора уже приберется за ними!
System.gc();

На самом деле прямой сбор мусора — это плохая идея, вроде как запереться в телефонной будке с бешеным питбулем. Точная семантика вызова зависит от реализации, но в предположении, что JVM работает со сборщиком мусора, основанным на понятии "поколение объектов" (а таких большинство), System.gc(); заставляет VM выполнить «полную зачистку» кучи, даже если в этом нет необходимости. Полная зачистка обычно обходится на несколько порядков дороже, чем регулярные операции GC.

Однако для решения этой конкретной проблемы инженеры Sun снабдили нас специальным JVM-флагом. Флаг -XX:+DisableExplicitGC автоматически превращает вызов System.gc() в no-op, предоставляя разработчику возможность запустить код и проверить, помогает ли операция System.gc() или вредит исполнению JVM в целом.

На JVM IBM ту же функцию, которая имеется на машинах JVM, основанных на технологии HotSpot, можно выполнить с помощью результата команды -Xdisableexplicitgc.


2. HeapDumpOnOutOfMemoryError

Случалось ли вам переживать такие дни, когда JVM загибается, выдавая сообщения OutOfMemoryError, а вы не можете заставить отладчик выловить причину? Такие спорадические или недетерминированные проблемы могут свести разработчика с ума.

Будьте бдительны

Не все флаги командной строки обязательно поддерживаются VM, если только она не от Sun/Oracle. Лучший способ выяснить, поддерживается ли флаг, конечно, ― попробовать его и посмотреть, работает ли он. Однако если эти флаги технически не поддерживаются, вы несете полную ответственность за их использование. Ни я, ни Sun/Oracle, ни IBM® не будут отвечать за то, что в результате применения любого из этих флагов испарились ваш код, данные, сервер или ваша мама. В качестве меры предосторожности я советую сначала проверить их в виртуальной (непроизводственной) среде.

В таких случаях нужно сделать моментальный снимок кучи прямо в тот момент, когда JVM испускает дух — и именно это делает команда -XX:+HeapDumpOnOutOfMemoryError.

По этой команде JVM делает «снимок дампа кучи» и сохраняет его в файле для последующей обработки, обычно с помощью утилиты jhat (которую я представил в предыдущей статье). Путь, по которому этот файл будет сохранен, можно указать с помощью соответствующего флага -XX:HeapDumpPath. (Где бы ни сохранялся этот файл, убедитесь, что файловая система и/или процесс Java имеет необходимую конфигурацию разрешений, чтобы записать его туда.)

В механизме дампа JVM IBM эта возможность включена по умолчанию, гарантируя получение heapdump при наличии OutOfMemoryError. Механизм дампа IBM обеспечивает ряд параметров конфигурации, включая запрет дампов, посредством параметров командной строки -Xdump.


3. bootclasspath

Полезно периодически направлять класс по пути classpath, который немного отличается от того, что входит в комплект JRE, или как-нибудь расширяет JRE. (Примером может служить новый поставщик API Java Crypto). Если нужно расширить JRE, то ваша специальная реализация должна быть доступна для загрузчика ClassLoader, который загружает java.lang.Object и всех его собратьев в rt.jar.

Хотя можно открыть rt.jar и ввести туда специальную реализацию или новый пакет, технически это было бы нарушением лицензии, с которой вы согласились, загружая JDK.

Вместо этого используйте собственный параметр JVM -Xbootclasspath и его сородичей -Xbootclasspath/p и -Xbootclasspath/a.

-Xbootclasspath позволяет задать полный путь загрузки classpath, который обычно должен включать ссылку на rt.jar, плюс куча других JAR-файлов, входящих в JDK и не являющихся частью rt.jar. -Xbootclasspath/p помещает значение в начало существующей переменной bootclasspath, а -Xbootclasspath/a ― в конец.

Если, к примеру, вы изменили массив java.lang.Integer и внесли изменения в подкаталог mods, то параметр -Xbootclasspath/a mods поместит новое значение Integer перед значением по умолчанию.


4. verbose

-verbose - полезная утилита диагностики первого уровня для Java-приложений практически любого типа. У этого флага три подфлага: gc, class и jni.

gc обычно становится первым, к чему прибегают разработчики, чтобы попытаться выяснить, не шалит ли сборщик мусора JVM и не стало ли это причиной низкой производительности. К сожалению, интерпретация выходных данных gc может оказаться затруднительной — настолько, что об этом можно написать целые книги. Еще хуже то, что данные, выводимые в командной строке, могут меняться от одного выпуска Java к другому или от одной JVM к другой, что еще больше затрудняет правильную интерпретацию.

Вообще говоря, если сборщик мусора основан на понятии "поколений объектов" (а таких в VM «корпоративного класса» большинство), тот или иной видимый флаг укажет на полный проход GC; в JVM Sun этот флаг выглядит как [Full GC ...] в начале выходной строки GC.

class может быть спасением при попытке диагностировать ClassLoader или при конфликтах несоответствия классов. Он указывает не только время загрузки класса, но и место, откуда он был загружен, включая путь к файлу JAR, если он поступил из JAR.

jni полезен лишь при работе с JNI и собственными библиотеками. Когда он включен, он сообщает о различных событиях JNI, таких как момент загрузки собственных библиотек и привязки методов; опять же результат может варьироваться от одного выпуска к другому или одной JVM к другой.


5. Command-line -X

Я перечислил некоторые из моих любимых параметров командной строки, предоставляемых JVM, но их очень много, так что читателю следовало бы провести собственное исследование. Запуск аргумента командной строки -X приводит к перечислению всех нестандартных (но в большинстве своем безопасных) аргументов, которые предоставляет JVM — например:

  • -Xint, который выполняет JVM в режиме интерпретации (это может быть полезно для проверки, оказывает ли JIT-компилятор влияние на код, и нет ли в нем ошибок);
  • -Xloggc:, который делает то же, что и -verbose:gc, но регистрирует события в файл, а не выбрасывает их в окно командной строки.

Параметры командной строки JVM время от времени меняются, так что полезно периодически просматривать их. От этого может зависеть, придется ли вам допоздна пялиться на монитор, или же вы придете домой в 5 часов вечера и сможете поужинать с супругой и детьми (или поубивать врагов в Mass Effect 2, смотря что вам больше нравится).

В JVM IBM вывод результатов verbose:gc в файл запрашивается с помощью параметра -Xverbosegclog, который также позволяет создать спецификацию файла журнала.


Заключение

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

Далее в цикле Пять секретов…: Java-инструменты на каждый день.

Ресурсы

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java, Open source
ArticleID=842880
ArticleTitle=Пять секретов... флагов командной строки JVM
publish-date=10262012