Це проблема, яку я намагаюся відстежити вже пару місяців. У мене запущена програма Java, яка обробляє xml-канали та зберігає результат у базі даних. Були періодичні проблеми з ресурсами, які дуже важко відстежити.
Довідкова інформація: У виробничій коробці (де проблема найбільш помітна) я не маю особливо хорошого доступу до коробки та не можу запустити Jprofiler. Цей ящик - це 64-бітна чотириядерна машина на 8 Гб, на якій працюють centos 5.2, tomcat6 та java 1.6.0.11. Починається з цих java-опцій
JAVA_OPTS="-server -Xmx5g -Xms4g -Xss256k -XX:MaxPermSize=256m -XX:+PrintGCDetails -
XX:+PrintGCTimeStamps -XX:+UseConcMarkSweepGC -XX:+PrintTenuringDistribution -XX:+UseParNewGC"
Стек технологій такий:
- Centos 64-розрядний 5.2
- Java 6u11
- Tomcat 6
- Весна / WebMVC 2.5
- Зимовий сон 3
- Кварц 1.6.1
- DBCP 1.2.1
- Mysql 5.0.45
- Ehcache 1.5.0
- (і звичайно безліч інших залежностей, зокрема бібліотеки jakarta-commons)
Найближче, що я можу отримати до відтворення проблеми, - це 32-розрядна машина з меншими вимогами до пам'яті. Що я справді контролюю. Я дослідив його до смерті за допомогою JProfiler і виправив багато проблем із продуктивністю (проблеми із синхронізацією, попередня компіляція / кешування запитів xpath, зменшення пулу потоків та видалення непотрібного попереднього вилучення в сплячий режим та надмірне «розігрівання кешу» під час обробки).
У кожному випадку профайлер показував, що вони забирають величезну кількість ресурсів з тих чи інших причин, і що це вже не були первинні свині ресурсів, як тільки зміни вступили.
Проблема: Схоже, JVM повністю ігнорує налаштування використання пам’яті, заповнює всю пам’ять і не реагує. Це проблема для замовника, котрий стикається з кінцем, який очікує регулярного опитування (5-хвилинна основа та 1-хвилинна повторна спроба), а також для наших оперативних команд, які постійно отримують повідомлення про те, що коробка перестала реагувати, і її потрібно перезапустити. На цій коробці немає нічого іншого значного.
Проблема, схоже, у вивозі сміття. Ми використовуємо колектор ConcurrentMarkSweep (як зазначено вище), оскільки оригінальний колектор STW викликав таймаути JDBC і ставав дедалі повільнішим. Журнали показують, що в міру збільшення використання пам'яті, тобто починає видавати помилки cms, і повертається до початкового колектору зупинки світу, який потім, здається, неправильно збирається.
Однак, працюючи з jprofiler, кнопка "Запустити GC", здається, добре очищає пам'ять, а не показує зростаючий відбиток, але оскільки я не можу підключити jprofiler безпосередньо до робочого вікна, і вирішення перевірених гарячих точок, здається, не працює, я працюю залишився з вуду налаштування сліпого збору сміття.
Що я пробував:
- Профілювання та фіксація гарячих точок.
- Використання збирачів сміття STW, Parallel та CMS.
- Запуск з мінімальним / максимальним розміром купи з кроком 1 / 2,2 / 4,4 / 5,6 / 6.
- Запуск із простіром пермгену з кроком 256 М до 1 Гб.
- Безліч поєднань вищесказаного.
- Я також проконсультувався з JVM [посиланням на налаштування] (http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html), але насправді не можу знайти нічого, що пояснює цю поведінку, або будь-які приклади налаштування _which_ параметри для використання в подібній ситуації.
- Я також (безуспішно) пробував jprofiler в автономному режимі, з'єднуючись з jconsole, visualvm, але, здається, не можу знайти нічого, що може взаємодіяти з моїми даними журналу gc.
На жаль, проблема також виникає епізодично, здається, це непередбачувано, вона може працювати кілька днів або навіть тиждень, не маючи жодних проблем, або може виходити з ладу 40 разів на день, і єдине, що я, здається, постійно ловлю що збирання сміття діє.
Хто-небудь може дати будь-яку пораду щодо:
а) Чому JVM використовує 8 фізичних концертів та 2 Гб місця для обміну, коли він налаштований на максимальне обмеження менше ніж 6.
b) Посилання на налаштування GC, яке насправді пояснює або дає обґрунтовані приклади про те, коли і з яким параметром використовувати розширені колекції.
в) Посилання на найпоширеніші витоки пам'яті Java (я розумію незатребувані посилання, але я маю на увазі на рівні бібліотеки / фреймворку або щось інше в inherenet в структурах даних, як хеш-карти).
Дякуємо за будь-яку інформацію, яку ви можете надати.
EDIT
Emil H:
1) Так, мій кластер розробки є дзеркалом виробничих даних, аж до медіасервера. Основною відмінністю є 32/64 біт та обсяг доступної оперативної пам'яті, яку я не можу дуже легко відтворити, але код, запити та налаштування однакові.
2) Існує деякий застарілий код, який спирається на JaxB, але при переупорядкуванні завдань, щоб уникнути конфліктів планування, я вважаю, що виконання, як правило, усувається, оскільки воно виконується один раз на день. Первинний аналізатор використовує запити XPath, які викликають пакет java.xml.xpath. Це було джерелом кількох гарячих точок, для одного запити не були попередньо скомпільовані, а два посилання на них були в жорстко закодованих рядках. Я створив безпечний кеш-пам'ять (hashmap) і врахував посилання на запити xpath як остаточні статичні рядки, що значно знизило споживання ресурсів. Запит все ще є значною частиною обробки, але це повинно бути тому, що це основна відповідальність програми.
3) Додаткова примітка, інший основний споживач - це операції із зображеннями від JAI (повторна обробка зображень із стрічки). Мені незнайомі графічні бібліотеки Java, але з того, що я виявив, вони не особливо діряві.
(дякую за відповіді поки що, люди!)
ОНОВЛЕННЯ:
Я зміг підключитися до виробничого екземпляра за допомогою VisualVM, але він відключив опцію візуалізації GC / run-GC (хоча я міг переглядати її локально). Цікава річ: розподіл купи ВМ підпорядковується JAVA_OPTS, а фактично виділена купа зручно сидить на рівні 1-1,5 концертів, і, здається, не витікає, але моніторинг рівня ящиків все ще показує схему витоку, але це не відображається у моніторингу ВМ. На цій коробці більше нічого не працює, тому я тупився.