Статьи

Превышен предел издержек GC — анализ кучи Java

Этот пост является продолжением нашего исходного поста о превышении предельных значений GC проблемных шаблонов. Правильный анализ кучи Java имеет решающее значение для устранения проблемы OutOfMemoryError: GC. Если вы не знакомы с этой ошибкой Java HotSpot 1.6, я рекомендую вам сначала просмотреть мою первую статью на эту тему.
Эта статья предоставит вам пример программы и учебное пособие о том, как анализировать объем кучи Java HotSpot с помощью анализатора памяти после OutOfMemoryError. Я настоятельно рекомендую вам выполнить и проанализировать дамп кучи самостоятельно, используя это руководство, чтобы лучше понять эти принципы.
Инструменты для устранения неполадок
** все эти инструменты можно скачать бесплатно **

  • Eclipse Indigo Release
  • Анализатор памяти через IBM Support Assistant 4.1 (анализ дампа кучи HotSpot)
  • Java VM: Windows HotSpot JRE 1.6.0_24 64-разрядная
Пример Java-программы
Простой пример Java-программы ниже будет использоваться для запуска OutOfMemoryError; что позволяет нам анализировать сгенерированный файл дампа кучи HotSpot. Просто создайте новый класс Java: JVMOutOfMemoryErrorSimulator.java для выбранного вами проекта Eclipse и переименуйте или сохраните текущий пакет как есть.
Эта программа в основном создает несколько экземпляров String в структуре данных Map до истощения кучи Java.
GC_overhead_Eclipse_Project
** пожалуйста, убедитесь, что ваш компилятор Eclipse и JRE равен 1.6 **
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package org.ph.javaee.javaheap;
 
import java.util.Map;
import java.util.HashMap;
 
/**
* JVMOutOfMemoryErrorSimulator
*
* @author PH
*/public class JVMOutOfMemoryErrorSimulator {
 
       private final static int NB_ITERATIONS = 500000;
 
       // ~1 KB data footprint      
       private final static String LEAKING_DATA_PREFIX = "datadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadat
adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata";
 
       // Map used to stored our leaking String instances      
       private static Map<String, String> leakingMap;
 
       static {             
              leakingMap = new HashMap<String, String>();      
       }
 
       /**       
        * @param args       
        */      
        public static void main(String[] args) {
 
              System.out.println("JVM OutOfMemoryError Simulator 1.0");         
              System.out.println("Author: Pierre-Hugues Charbonneau");         
              System.out.println(" http ://javaeesupportpatterns.blogspot.com/");
 
              try {
 
                     for (int i = 0; i < NB_ITERATIONS; i++) {
 
                          String data = LEAKING_DATA_PREFIX + i;
 
                          // Add data to our leaking Map data structure...     
                          leakingMap.put(data, data);
 
                     }
 
              } catch (Throwable any) {                    
                     if (any instanceof java.lang.OutOfMemoryError){
                             System.out.println("OutOfMemoryError triggered! "
                                         + any.getMessage() + " [" + any + "]");
 
                     } else {                          
                           System.out.println("Unexpected Exception! " +
                                   any.getMessage() + " [" + any + "]");
                            }             
                     }
 
                     System.out.println("simulator done!");      
            }
 
}
Шаг № 1 — Настройте параметры запуска JVM
Сначала настройте аргументы времени выполнения Eclipse Java, как показано ниже. Для нашего примера мы использовали внешнюю JRE 1.6 вне Eclipse IDE с максимальной емкостью кучи Java 512 МБ.
Ключевым аргументом JVM, позволяющим нам генерировать дамп кучи, является -XX: + HeapDumpOnOutOfMemoryError, который говорит JVM сгенерировать дамп кучи после условия OutOfMemoryError.
GC_overhead_Run_Configuration
GC_overhead_Run_Configuration_JVM
Шаг № 2 — Запустите образец Java-программы
Следующим шагом является запуск нашей Java-программы. В зависимости от спецификаций вашего компьютера, эта программа будет работать за 5-30 секунд до того, как возникнет ошибка OutOfMemoryError.
GC_overhead_Run_Java_Program_Exec
Как видите, JVM сгенерировала файл дампа кучи java_pid3880.hprof. Теперь пришло время запустить инструмент Memory Analyzer и проанализировать дамп кучи JVM.

Шаг № 3 — Загрузите дамп кучи
Анализ дампа кучи — это анализ, который может быть простым или очень сложным. Цель этого руководства — дать вам основы анализа дампа кучи. Более подробный анализ дампа кучи приведен в других тематических исследованиях этого блога.
GC_overhead_Heap_Dump_analysis1
GC_overhead_Heap_Dump_analysis2
GC_overhead_Heap_Dump_analysis3
Шаг № 4 — Анализ дампа кучи
Ниже приведены снимки и шаги анализа, которые вы можете выполнить, чтобы понять утечку памяти, которую мы смоделировали в нашем примере программы Java.
GC_overhead_Heap_Dump_analysis4
GC_overhead_Heap_Dump_analysis5
GC_overhead_Heap_Dump_analysis6
GC_overhead_Heap_Dump_analysis7
Как вы можете видеть, анализ дампа кучи с помощью инструмента Memory Analyzer позволил легко идентифицировать наш первичный утекший класс Java и структуру данных.
Вывод
Я надеюсь, что эта простая программа на Java и руководство по анализу дампа кучи помогли вам понять основные принципы анализа кучи Java с использованием необработанных данных дампа кучи. Этот анализ является критическим при работе с OutOfMemoryError: проблемы с загрузкой GC, так как они являются признаками утечки кучи Java или проблемы с настройкой кучи Java.