Десь кілька місяців тому виявилося, що в проекті, над яким я працюю, знайшлася потворна бага. Відловити її було неможливо. В будь-який момент працювати з програмою ставало неможливо. В логах вивалювалася помилка OutOfMemoryError: PermGen
.
Звичайно, я з цим не вперший раз стикаюся, і вирішив спробувати старий добрий спосіб - прописати параметр до Джава машини -XX:MaxPermSize
. Отже, прописавши параметр -XX:MaxPerSize=256m
, я запустив JBoss
. І що? А нічого. Все одно програма вивалювалася... Так само непердбачувано і неочікувано :(.
Тоді я вирішив спробувати ще раз, але цього разу збільшив память для PermGen space вдвічі: -XX:MaxPerSize=512m
. Особливо це мені не допомогло, добитися впевнених 24/7 так і невийшло. І було вирішено, що слід ритися вглубь, не виправляти проблему, а викорінити причину!
Порившись в інтернеті я надибав блог by Frank Kieviet, в якому розповідалося про використання утиліт для Java 6: jmap
та jhat
. jmap
- дозволяє створювати дампи пам'яті Java програми.jhat
- дозволяє представити інформацію дампа у зручному для користувача вигляді.
Отож, використовуючи jmap я зробив дамп heap пам'яті запущеної програми в процесі її роботи. Я виконав команду>jmap -dump:format=b,file=dump1 3412
цим самим вказавши, що слід виконати дамп пам'яті програми, зберегти її в бінарному форматі у файлі dump1. 3412
- це pid Java програми, дамп пам'яті якої я робив. Для того, щоб отримати ідентифікатор процесу, у Windows введіть команду tasklist
і знайдіть відповідний java.exe
процес.
Після того, як в мене вже був збережений у файлі дамп, я скористався програмою jhat
. Команда:>jhat dump1
проаналізувала дамп і запустила веб-сервер, який по-замовчуванню слухає запити на порті 7000. Якщо потрібно буде одночасно запустити декілька jhat, то знайте - адрес порта можна змінити відповідним параметром. Слід також звернути увагу на параметр -J
. Всі параметри, які задаються після -J
потрапляються напряму до Java машини. В моєму випадку це знадобилося для того, щоб збільшити максимальну межу пам'яті, яку можна виділити. У випадку програми, яка працювала під JBoss AS 4.0.4, я змушений був запускати jhat
компандою
>jhat -J-Xmx1536m dump
Після старту jhat
, можна спокійно відкривати ваш олюблений броузер, і вводити адрес http://localhost:7000/. Тепер можна переглядати дамп пам'яті програми, використовуючи набір функціоналу, який надається програмою.
Скориставшися цією програмою, я визначив причину моєї проблеми – не всі динамічно генеровані класи вигружалися; декотрі з них так і залишалися назавжди в пам'яті. Оскільки, PermGen Space (Permananent Generated Space) - це простір в пам'яті, в якому знаходяться довгоживучі (або вічноживучі в межах запущеної java-машини) об'єкти, а серед таких є класи та 'interned strings', то зрозуміло, що суть моєї проблеми в тому, що декотрі динамічно генеровані класи продовжували генеруватися, завантажуватися в пам'ять, але навідмінно від інших, вони залишалися там навічно. Рано чи пізно вільна пам'ять завершувалася, і програма уходила в аут із знойним повідомленням "OutOfMemoryError: PermGen".
Але лікування цієї проблеми це вже зовсім інша історія... І наразі вона ще не закінчилася :(.
OutOfMemoryError: PermGen
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment