← Назад к вопросам

Что произойдет с объектом, если им никто не пользуется?

1.7 Middle🔥 201 комментариев
#JVM и управление памятью

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Что произойдет с объектом, если им никто не пользуется?

Ответ: объект будет удален Garbage Collector (сборщик мусора) и его память освобождена для использования другими объектами.

Жизненный цикл объекта в Java

1. Создание    → new Object()
2. Использование → ссылка на объект существует
3. Недостижимость → нет ссылок на объект
4. Garbage Collection → JVM удаляет объект
5. Освобождение памяти → память возвращена в heap

Понятие "никто не пользуется"

// Есть ссылка - объект в памяти
User user = new User("John");
System.out.println(user.getName()); // используется

// Удаляем ссылку - объект больше не используется
user = null;
// или выход из scope
{
    User localUser = new User("Jane");
    // используется
} // localUser выходит из scope → ссылка теряется

// Объект становится недостижимым (unreachable)
// GC заметит это и удалит объект

Как JVM определяет недостижимость?

Mark and Sweep алгоритм

1. Mark фаза: JVM ищет все ссылки на объекты
   - Начинает с корневых ссылок (локальные переменные, static поля)
   - Помечает достижимые объекты
   
2. Sweep фаза: JVM удаляет непомеченные объекты
   - Освобождает память
   - Уплотняет heap

Пример garbage collection

public class GarbageCollectionExample {
    public static void main(String[] args) {
        // Объект 1: создан
        User user1 = new User("Alice");
        
        // Объект 2: создан
        User user2 = new User("Bob");
        
        // Переприсваиваем ссылку
        user1 = user2; // объект Alice больше не достижим!
        // GC удалит объект Alice
        
        // Обнуляем ссылку
        user2 = null; // объект Bob становится недостижимым
        // GC удалит объект Bob
    }
    // Конец метода - локальные переменные удаляются
}

Когда запускается GC?

  1. Автоматически когда heap переполнен
  2. System.gc() явный вызов (не гарантирован)
  3. Зависит от JVM (G1GC, ZGC, CMS и т.д.)

Проблемы с забытыми ссылками

Memory Leak: забыли удалить ссылку

public class Cache {
    private List<User> cache = new ArrayList<>();
    
    public void addUser(User user) {
        cache.add(user); // добавили в cache
    }
    
    // ПРОБЛЕМА: нет метода для удаления из cache
    // cache будет расти и никогда не очищаться!
}

Решение: WeakReference

public class SmartCache {
    private Map<String, WeakReference<User>> cache = new WeakHashMap<>();
    
    public void addUser(String key, User user) {
        cache.put(key, new WeakReference<>(user));
    }
    
    // Если на пользователя нет других ссылок,
    // он будет удален GC, даже если в cache
}

Типы ссылок в Java

// 1. Strong reference (обычная ссылка)
User user = new User(); // будет удалён только если user = null

// 2. Weak reference
WeakReference<User> weakUser = new WeakReference<>(user);
// Если нет других ссылок, GC удалит объект

// 3. Soft reference
SoftReference<User> softUser = new SoftReference<>(user);
// GC удалит только если мало памяти

// 4. Phantom reference
PhantomReference<User> phantomUser = new PhantomReference<>(user, queue);
// Уведомляет о готовности к удалению

Финализация объектов

finalize() метод (устаревший)

public class Resource {
    private Connection conn;
    
    @Override
    protected void finalize() throws Throwable {
        if (conn != null) {
            conn.close(); // очистка при удалении
        }
        super.finalize();
    }
}

Проблемы:

  • finalize() может не вызваться никогда
  • Замедляет GC
  • Сложно предсказать когда вызовется

Правильный способ: try-with-resources

try (Connection conn = getConnection()) {
    // использование
} // автоматически закроется

Мониторинг памяти

public class MemoryMonitor {
    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        
        long usedMemory = runtime.totalMemory() - runtime.freeMemory();
        System.out.println("Used: " + usedMemory / 1024 / 1024 + " MB");
        
        // Принудительно запустить GC (не рекомендуется)
        System.gc();
        
        usedMemory = runtime.totalMemory() - runtime.freeMemory();
        System.out.println("After GC: " + usedMemory / 1024 / 1024 + " MB");
    }
}

Лучшие практики

  1. Не полагайся на finalize()
  2. Используй try-with-resources для ресурсов
  3. Избегай memory leaks через WeakReference
  4. Не вызывай System.gc() без необходимости
  5. Профилируй память если нужно

Резюме

Объект, на который нет ссылок, становится недостижимым. Garbage Collector заметит это и удалит объект, освободив память. В Java управление памятью автоматическое, что избавляет от manual memory management как в C++.

Что произойдет с объектом, если им никто не пользуется? | PrepBro