AFAIK, специфікація JVM (написана англійською мовою) не вказує, коли саме об'єкт (або значення) слід видалити, і залишає це для реалізації (подібно до R5RS ). Це якось вимагає або пропонує сміттєзбірник, але деталі залишає для реалізації. І так само для специфікації Java.
Пам’ятайте, що мови програмування - це специфікації ( синтаксису , семантики тощо), а не реалізація програмного забезпечення. Мова на зразок Java (або її JVM) має багато реалізацій. Його специфікація публікується , завантажується (щоб ви могли вивчити її) та написана англійською мовою. §2.5.3 Купи специфікацій JVM згадують сміттєзбірник:
Зберігання купи об’єктів відновлюється системою автоматичного управління зберіганням (відома як сміттєзбірник); об'єкти ніколи прямо не розміщуються. Віртуальна машина Java не передбачає конкретного типу автоматичного управління зберіганням
(акцент мій; доопрацювання BTW згадується в §12.6 специфікації Java, а модель пам'яті - в §17.4 специфікації Java)
Тож (на Java) вам не варто піклуватися про те, коли об’єкт видаляється , і ви можете кодувати так, як якщо б це не сталося (міркуючи в абстракції, де ви ігноруєте це). Звичайно, вам потрібно подбати про споживання пам’яті та набір живих об’єктів, це вже інше питання. У кількох простих випадках (подумайте про програму "привіт світ") ви зможете довести - або переконати себе - що виділена пам'ять досить мала (наприклад, менше, ніж гігабайт), і тоді вам зовсім не байдуже видалення окремих об'єктів. У більшості випадків можна переконати себе, що живі об’єкти(або доступні, які є надмірним - легше міркувати про - живих) ніколи не перевищують розумного ліміту (і тоді ви покладаєтесь на GC, але вам все одно, як і коли відбувається сміття). Читайте про складність простору .
Я здогадуюсь, що у кількох реалізаціях JVM, які запускають короткочасну програму Java, як привіт, світ, збирач сміття взагалі не спрацьовує, і видалення не відбувається. AFAIU, така поведінка відповідає численним специфікаціям Java.
Більшість реалізацій JVM використовують поколінні методи копіювання (принаймні, для більшості об’єктів Java, тих, що не використовують фіналізацію або слабкі посилання ; і доопрацювання не гарантується, що відбудеться за короткий час і може бути відкладено, тому це просто корисна функція, що ваш код не повинен багато в чому залежать від), в якому поняття про видалення окремого об'єкта не має жодного сенсу (оскільки великий блок пам'яті, що містить зони пам'яті для багатьох об'єктів, можливо, відразу кілька мегабайт, вивільняється одразу).
Якщо специфікація JVM вимагає видалення кожного об'єкта якнайшвидше (або просто обмеження для видалення об'єкта), ефективні поколінні методи GC були б заборонені, і дизайнери Java та JVM з розумом уникали цього.
До речі, можливо, наївний JVM, який ніколи не видаляє об'єкти і не звільняє пам'ять, може відповідати специфікаціям (літера, а не дух) і, безумовно, здатний на практиці запустити привіт у світі (зауважте, що більшість крихітні та недовговічні програми Java, мабуть, не виділяють більше кількох гігабайт пам'яті). Звичайно, такий JVM не варто згадувати і є лише іграшкою (як це реалізація malloc
для C). Див. Epsilon NoOp GC для отримання додаткової інформації. Реалістичні JVM - це дуже складні програми та поєднують декілька методів збору сміття.
Крім того, Java не є тим самим, що й JVM, і у вас є реалізація Java, що працює без JVM (наприклад, дострокові компілятори Java, час виконання Android ). У деяких випадках (здебільшого академічні) ви можете уявити собі (так звані методи "збирання сміття під час компіляції"), що програма Java не виділяє та не видаляє під час виконання (наприклад, тому що компілятор оптимізації був досить розумним, щоб використовувати лише стек виклику та автоматичні змінні ).
Чому об’єкти Java не видаляються відразу після того, як на них більше не посилаються?
Оскільки специфікації Java та JVM цього не потребують.
Прочитайте посібник з GC для отримання додаткової інформації (та специфікації JVM ). Зауважте, що живий (або корисний для майбутніх обчислень) об’єкт - це властивість цілої програми (немодульна).
Objective-C віддає перевагу підходу підрахунку посилань до управління пам'яттю . І це також має підводні камені (наприклад, Objective-C програміст повинен піклуватися про циклічних посиланнях на expliciting слабких посилань, але JVM обробляє циклічні посилання добре на практиці , не вимагаючи уваги з боку програміста Java).
Там немає срібної кулі в програмуванні та розробці мов програмування (бути в курсі Проблеми Зупинки , будучи корисним живим об'єктом є нерозв'язним в цілому).
Ви також можете прочитати SICP , Прагматику мови програмування , Книгу Драконів , Слухати невеликими п’єсами та Операційні системи: Три простих п’єси . Вони не про Java, але вони відкриють вам розум і повинні допомогти зрозуміти, що повинен робити JVM і як це може практично працювати (з іншими фрагментами) на вашому комп'ютері. Ви також можете витратити багато місяців (або кілька років) на вивчення складного вихідного коду існуючих реалізацій JVM з відкритим кодом (наприклад, OpenJDK , який має кілька мільйонів рядків вихідного коду).