Основные проблемы с памятью Java
В этом разделе объясняются часто возникающие проблемы с памятью, такие как утечки памяти, высокий уровень использования памяти, проблемы с загрузчиком классов и конфигурация сборщика мусора.
Утечки памяти
Наиболее распространенная проблема утечки памяти - это растущие утечки памяти или постоянный рост утечек объектов. Эти утечки можно легко отследить с помощью дампов трендов или гистограмм.
Для сравнения, об утечках отдельных объектов говорят меньше. Пока памяти достаточно, одиночные утечки памяти редко представляют серьезную проблему. Однако время от времени утечки отдельных объектов занимают значительный объем памяти и создают проблемы. Хорошая новость заключается в том, что отдельные большие утечки можно легко обнаружить с помощью инструментов анализа кучи.
Ниже приведены некоторые из причин утечки памяти:
Thread local variables
ThreadLocal
variables are used to bind a variable or a state to a thread. Each thread has its own instance of the variable. WhileThreadLocal
variables can be useful, they can also be dangerous. They are used to track a state, such as the current transaction ID, but sometimes hold some more information. AThreadLocal
variable is referenced by its thread and its lifecycle is bound to it. In most application servers, threads are reused via thread pools and are never garbage collected. If the application code does not carefully clear theThreadLocal
variable, it results in a nasty memory leak. Such leaks can be easily discovered with a heap dump by looking at theThreadLocalMap
and following the references. In the above screen, the heapdump indicates that over 4K objects, which amount to around 10MB in size, are held byThreadLocal
variables. The name of the thread reveals the part of the application that is responsible for the leak.
Mutable static fields and collections
- The most common reason for a memory leak is the wrong usage of statics. A static variable is held by its class and, subsequently, by its classloader. While a class can be garbage collected, it will seldom happen during an application's lifetime. Often, statics are used to hold cache information or share state across threads. If this is not done diligently, it is easy to get a memory leak. For this reason, static mutable collections must be avoided at all costs. A good architectural rule is to not use mutable static objects at all and settle for better alternatives.