AFAIK, спецификация JVM (написана на английском языке) не упоминает, когда именно объект (или значение) должен быть удален, и оставляет это для реализации (аналогично для R5RS ). Это как-то требует или предлагает сборщик мусора, но оставляет детали для реализации. И аналогично для спецификации Java.
Помните, что языки программирования - это спецификации ( синтаксиса , семантики и т. Д.), А не программные реализации. Язык как Java (или его JVM) имеет много реализаций. Его спецификация опубликована , доступна для скачивания (чтобы вы могли ее изучить) и написана на английском языке. §2.5.3 В куче спецификации JVM упоминается сборщик мусора:
Куча хранилища для объектов восстанавливается автоматической системой управления хранилищем (известной как сборщик мусора); объекты никогда не освобождаются явно. Виртуальная машина Java не предполагает конкретного типа автоматической системы управления хранением
(акцент мой; финализация BTW упоминается в §12.6 спецификации Java, а модель памяти - в §17.4 спецификации Java)
Поэтому (в Java) вас не должно волновать, когда объект удаляется , и вы можете кодировать как-будто это не происходит (рассуждая в абстракции, где вы игнорируете это). Конечно, вам нужно заботиться о потреблении памяти и множестве живых объектов, это другой вопрос. В нескольких простых случаях (например, программа «Здравствуй, мир») вы можете доказать - или убедить себя - что выделенная память довольно мала (например, меньше гигабайта), и тогда вам все равно удаление отдельных объектов. В большем количестве случаев вы можете убедить себя, что живые объекты(или достижимые, которые являются надмножеством - проще для рассуждений о живых) никогда не превышают разумный предел (и тогда вы полагаетесь на GC, но вам все равно, как и когда происходит сборка мусора). Читайте о космической сложности .
Я предполагаю, что в нескольких реализациях JVM, работающих с недолговечной Java-программой, такой как hello world, сборщик мусора вообще не запускается и удаление не происходит. AFAIU, такое поведение соответствует многочисленным спецификациям Java.
В большинстве реализаций JVM используются методы копирования поколений (по крайней мере, для большинства объектов Java, тех, которые не используют финализацию или слабые ссылки ; завершение не гарантируется в течение короткого времени и может быть отложено, так что это всего лишь полезная функция, которую ваш код не должен во многом зависит от), в котором понятие удаления отдельного объекта не имеет никакого смысла (поскольку большой блок памяти, содержащий зоны памяти для многих объектов, - возможно, несколько мегабайт одновременно, освобождается одновременно).
Если бы спецификация JVM требовала, чтобы каждый объект был удален точно как можно скорее (или просто наложил бы больше ограничений на удаление объекта), эффективные методы генерации GC были бы запрещены, и разработчики Java и JVM были бы мудры избегать этого.
Кстати, вполне возможно, что наивная JVM, которая никогда не удаляет объекты и не освобождает память, может соответствовать спецификациям (букве, а не духу) и, безусловно, способна на практике использовать мир приветствия (обратите внимание, что большинство крошечные и недолговечные Java-программы, вероятно, не выделяют более нескольких гигабайт памяти). Конечно, о такой JVM не стоит упоминать, и это просто игрушка (как в этой реализации malloc
для C). См. Epsilon NoOp GC для получения дополнительной информации. Реальные виртуальные машины Java являются очень сложными программными компонентами и сочетают в себе несколько методов сбора мусора.
Кроме того, Java отличается от JVM, и у вас есть реализации Java, работающие без JVM (например, опережающие компиляторы Java, среда выполнения Android ). В некоторых случаях (в основном академических) вы можете себе представить (так называемые методы «сборки мусора во время компиляции»), что Java-программа не выделяет и не удаляет во время выполнения (например, потому что оптимизирующий компилятор достаточно умен, чтобы использовать только стек вызовов и автоматические переменные ).
Почему объекты Java не удаляются сразу после того, как на них больше нет ссылок?
Потому что спецификации Java и JVM этого не требуют.
Прочтите руководство GC для получения дополнительной информации (и спецификации JVM ). Обратите внимание, что наличие объекта (или полезного для будущих вычислений) для объекта является свойством всей программы (немодульным).
Objective-C предпочитает подход подсчета ссылок к управлению памятью . И это также имеет подводные камни (например, Objective-C программист должен заботиться о циклических ссылках на expliciting слабых ссылок, но JVM обрабатывает циклические ссылки хорошо на практике , не требуя внимания со стороны программиста Java).
В программировании и разработке языков программирования не существует «Серебряной пули» (помните о проблеме остановки ; быть полезным живым объектом в целом неразрешимо ).
Вы также можете прочитать SICP , Прагматика языка программирования , Книга Дракона , Lisp In Small Pieces и Операционные системы: Три простых компонента . Они не о Java, но они откроют вам разум и должны помочь понять, что должна делать JVM и как она может практически работать (с другими компонентами) на вашем компьютере. Вы также можете потратить много месяцев (или несколько лет) на изучение сложного исходного кода существующих реализаций JVM с открытым исходным кодом (например, OpenJDK , который имеет несколько миллионов строк исходного кода).