TGViewer
Библиотека джависта | Java, Spring, Maven, Hibernate Библиотека джависта | Java, Spring, Maven, Hibernate @javaproglib · 22K subscribers
Post #7428 2.58K
💥 Разрушим частый миф

Мне НЕ нужно разбираться с управлением памятью в Java, так как за меня всё делает GC


Garbage Collector (GC) действительно очищает неиспользуемые объекты, которые больше не имеют активных ссылок. Благодаря этому в Java не нужно вручную освобождать память, как в C++.

Несколько предпосылок к исходному тезису:

🔹 В других языках, где ручное управление памятью (C, C++), утечки очевидны — если забыл free(), память навсегда потеряна.
🔹 В Java GC работает автоматически, поэтому кажется, что он решает все проблемы сам.
🔹 "Ну раз GC есть, значит, про память можно не думать!" — типичная ошибка.

GC удаляет только те объекты, которые больше не имеют активных ссылок. Если же объект остаётся доступным, но фактически не используется, он будет занимать память до завершения работы приложения.

🔽 Несколько случаев утечек памяти

1️⃣ Статические коллекции (заполняем, но не чистим)

Если создать static List и постоянно добавлять в него объекты, они никогда не будут удалены GC, потому что статические поля живут весь срок жизни приложения.

public class MemoryLeak {
private static final List<byte[]> cache = new ArrayList<>();

public static void main(String[] args) {
while (true) {
cache.add(new byte[10 * 1024 * 1024]);
System.out.println("Добавили 10MB в кеш. Используемая память: " +
(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024) + "MB");
}
}
}


Через пару минут — OutOfMemoryError

2️⃣ Потоковые переменные (ThreadLocal)

Объекты, хранящиеся в ThreadLocal, привязываются к потоку, а в пуле потоков они могут жить дольше, чем нужно.

public class ThreadLocalLeak {
private static final ThreadLocal<byte[]> threadLocalData = new ThreadLocal<>();

public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);

for (int i = 0; i < 10; i++) {
executor.execute(() -> {
threadLocalData.set(new byte[10 * 1024 * 1024]); // 10MB на поток
System.out.println("Память занята потоком!");
});
}

executor.shutdown();
}
}


Поток завершится, а память останется занята, потому что ThreadLocal не очищается автоматически.

3️⃣ Внутренние классы и "утекшие" ссылки

Если анонимный класс или лямбда-ссылка ссылается на внешний объект, она может мешать GC очистить его.

public class InnerClassLeak {
private String data = "Очень важные данные";

public void createAnonymousClass() {
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("Используем: " + data);
}
};
new Thread(task).start();
}
}


task ссылается на data, даже если InnerClassLeak больше не используется → GC не очистит объект.

👎 Миф разрушен. GC не всемогущий и даже с ним придётся изучать, как работать с памятью в Java.

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#CoreJava
  • 👍 17
  • ❤ 5
  • 🔥 3
More from @javaproglib
  1. Oct 17, 2026☕️ Скользящие окна в Stream без ручного буфера Нужно сравнить соседние измерения или обраб…
  2. Oct 16, 2026🧑‍💻 Какие навыки помогают вам в разработке в 2026 году? Что вы чаще используете в работе…
  3. Oct 16, 2026🧩 Неизменяемый список всё ещё может измениться Collections.unmodifiableList() запрещает м…
  4. Oct 15, 2026💡 Logpoints: логи без правки кода и нового деплоя Чтобы увидеть значение переменной, необ…
  5. Oct 14, 2026Post #7897
  6. Oct 14, 2026Почему разработчик планирует отдавать больше задач Claude Винсент Шмальбах описал план пер…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →