Java – это язык программирования сборщика мусора. Что это значит для вас?
Я имею в виду, что язык позаботится об очистке неиспользуемых объектов в вашей программе. Если вы пришли с такого языка, как C/C++, вы почувствуете, что это похоже на сверхдержаву, потому что вам не нужно вручную очищать память для объектов, которые вы больше не используете (задача, о которой разработчик часто забывает).
Java сотворила волшебство с помощью своего алгоритма сборки мусора. В настоящее время их очень много но в основном он будет проверять наличие ссылки на выполняемую в данный момент программу с объектами, которые существуют в куче. Если есть какой-либо объект, на который программа не ссылалась, она очистит эти объекты, поскольку рассматривает их как мусор.
Давайте рассмотрим этот пример, который я взял из книги:
class PoolObjects { private static int DEFAULT_POOL_SIZE = 100; private int size = 0; private static Object[] pools; public PoolsObjects() { this.pools = new Object[DEFAULT_POOL_SIZE]; } public void add(Object o) { this.ensurePoolSize(); this.pools[this.size++] = o; } public Object pop() { if (this.size == 0) { throw new EmptyPoolException(); } Object r = this.pools[--size]; return r; } private void ensurePoolCapacity() { if (this.pools.length = this.size) { this.pools = Arrays.copyOf(this.pools, 2 * size + 1); } }
В приведенном выше примере есть очень тонкая точка утечки памяти. Как вы можете догадаться, по мере уменьшения размера массива элемент, индекс которого меньше значения size, будет неактивным или должен быть отброшен и очищен GC. Но на самом деле этого не будет, потому что на этот объект все еще ссылаются pools
переменная.
Один из способов устранить проблему – обнулить элемент, на который больше не ссылались.
public Object pop() { if (this.size == 0) { throw new EmptyPoolException(); } Object r = this.pools[--size]; this.pools[size] = null; // Explicitly nulling out the element at size index. return r; }
Я хотел бы завершить блог каким-нибудь банальным утверждением о том, что может произойти утечка памяти.
- Приложение, которое само управляет памятью. Приведенный выше пример
- Приложение, которое использует кеши. Кэшированный объект может оставаться в памяти вечно.
- Прослушиватель или обратный вызов, который регистрируется, но не отменяет регистрацию.
Оригинал: “https://dev.to/htintrinh/effective-java-7-obsolete-object-and-memory-leak-n5o”