Про це циклі статей
Ви думаєте, що знаєте про Java-програмуванні все? Насправді більшість розробників тільки шкребе по поверхні платформи Java, вивчивши її лише настільки, щоб виконувати свою роботу. У цьому циклі статей Тед Ньюард поглиблюється в функціональні можливості платформи Java, виявляючи маловідомі факти, які можуть допомогти у вирішенні найбільш хитромудрих завдань програмування.
JVM - робоча конячка, яка забезпечує функціональність і продуктивність Java-додатків і яку більшість Java-розробників приймає як належне. І далеко не всі дійсно розуміють, як JVM робить те, що вона робить - такі речі, як розподіл об'єктів і збір сміття, розгортання потоків, відкриття і закриття файлів, інтерпретація і / або JIT-компіляція байт-коду Java і багато іншого.
Незнання JVM дорого обходиться з точки зору продуктивності додатків, а коли щось йде не так, воно може сильно ускладнити спроби виправити становище.
1. DisableExplicitGC
Розвинути навички по цій темі
Цей матеріал - частина knowledge path для розвитку ваших навичок. Дивись Стати Java-програмістом
Я не можу сказати, скільки разів, коли мене просили проконсультувати з проблеми продуктивності додатків, швидкий grep за кодом показував те, що наведено в лістингу 1 - класичну антімодель продуктивності Java.
Лістинг 1. System.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-інструменти на кожен день.