Шрифт:
Оперативная память не бесконечна, и поэтому вполне возможно, что оператору new не удастся выделить память для объекта из-за нехватки доступной памяти. В этом случае возникает исключительная ситуация во время выполнения (подробнее об обработке исключительных ситуаций речь пойдет в главе 9). В примерах программ, представленных в этой книге, ситуация, связанная с исчерпанием оперативной памяти, не учитывается, но при написании реальных программ такую возможность, вероятно, придется принимать во внимание. "Сборка мусора" и методы завершения
Как было показано выше, при использовании оператора new свободная память для создаваемых объектов динамически выделяется из доступной буферной области оперативной памяти. Разумеется, оперативная память не бесконечна, и поэтому свободно доступная память рано или поздно исчерпывается. Это может привести к неудачному выполнению оператора new из-за нехватки свободной памяти для создания требуемого объекта. Именно по этой причине одной из главных функций любой схемы динамического распределения памяти является своевременное освобождение памяти от неиспользуемых объектов, чтобы сделать ее доступной для последующего перераспределения. Во многих языках программирования освобождение распределенной ранее памяти осуществляется вручную. Например, в C++ для этой цели служит оператор delete. Но в Java применяется другой, более надежный подход: “сборка мусора”.
Система “сборки мусора” в Java освобождает память от лишних объектов автоматически, действуя подспудно, незаметно и без всякого вмешательства со стороны программиста. “Сборка мусора” происходит следующим образом. Если ссылки на объект отсутствуют, то такой объект считается больше ненужным, и занимаемая им память в итоге освобождается. Эта утилизированная память может быть затем распределена для других объектов.
“Сборка мусора” происходит лишь время от времени по ходу выполнения программы. Она не состоится только потому, что существует один или несколько объектов, которые больше не используются. Следовательно, нельзя заранее знать или предположить, когда именно произойдет “сборка мусора”. Метод finalize
Существует возможность определить метод, который будет вызван непосредственно перед окончательным удалением объекта из памяти. Этот метод называется finalize. Он позволяет убедиться, что объект больше не существует. Этот метод можно, например, использовать для закрытия файла, открытого проверяемым объектом.
Для того чтобы добавить в класс метод завершения, достаточно определить метод finalize . Исполняющая система Java вызовет этот метод перед фактическим удалением объекта. В теле метода finalize следует предусмотреть действия, которые должны быть выполнены непосредственно перед удалением объекта.
Ниже приведена общая форма метода finalize. protected void finalize { // здесь указывается код метода завершения }
Ключевое слово protected является здесь спецификатором, предотвращающим обращение к методу finalizeO за пределами класса. Этот и другие спецификаторы доступа подробнее рассматриваются в главе 6.
Следует, однако, иметь в виду, что метод finalize вызывается непосредственно перед операцией “сборки мусора” по отношению к удаляемому объекту. Но он не вызывается в том случае, если объект оказывается за пределами области действия. Поэтому заранее невозможно предсказать, когда и при каких условиях метод finalize будет выполнен. Так, если программа завершится до того, как будет запущена процедура “сборки мусора”, метод finalize не будет выполнен. Таким образом, данный метод не пригоден для корректного освобождения занятых ресурсов или для других специальных целей, а тем более для нормального завершения работы программы. Короче говоря, метод finalize имеет специальное назначение и поэтому редко требуется для завершения большинства программ.
Пример для опробования 4.2. Демонстрация "сборки мусора" и завершения ко^а
В связи с тем что “сборка мусора” начинается в произвольные моменты времени и выполняется в фоновом режиме, продемонстрировать ее действие не так-то просто, но это можно все же сделать с помощью метода finalize. Напомним, этот метод вызывается в тот момент, когда объект должен быть удален. Но, как пояснялось ранее, объект не обязательно удаляется именно тогда, когда необходимость в нем отпадает. Вместо этого система “сборки мусора” дожидается того момента, когда освобождение памяти может быть произведено наиболее эффективно. Чаще всего для этого должно накопиться достаточно большое количество неиспользуемых объектов. Поэтому для демонстрации “сборки мусора” с помощью метода finalize нужно создать и удалить как можно больше объектов, что и предстоит сделать в данном проекте.
Последовательность действий
Создайте новый файл Finalize.java.
Создайте класс FDemo, как показано ниже. class FDemo { int х;
FDemo(int i) { x = i;
}
// вызывается при утилизации объекта protected void finalize { System.out.println("Finalizing " + x); }
// формирует объект, который тотчас уничтожается void generator(int i) { FDemo о = new FDemo(i).;
} }
В конструкторе данного класса устанавливается значение переменной экземпляра х, определяемое передаваемым параметром. В данном примере переменная экземпляра х служит в качестве идентификатора объекта. При утилизации объекта метод finalize отображает значение переменной х. Обратите особое внимание на метод generator . В нем создается объект типа FDemo, который сразу же уничтожается. Этот метод будет использован в дальнейшем.
Создайте класс Finalize, как показано ниже.class Finalize { public static void main(String args[]) { int count; FDemo ob = new FDemo(0); /* А теперь сформировать большое количество объектов. В какой-то момент должна начаться "сборка мусора". Примечание: количество формируемых объектов, возможно, придется увеличить, чтобы принудить "сборку мусора". */ for(count=l; count < 100000; count++) ob.generator(count); } }
В классе Finalize сначала создается исходный объект ob типа FDemo. Затем из этого объекта формируется 100000 других аналогичных объектов. С этой целью вызывается метод generator для объекта ob. На различных этапах данного процесса вступает в действие процедура “сборки мусора”. Частота активизации данной процедуры зависит от целого ряда факторов, в том числе от объема свободной памяти и типа операционной системы. Но в любом случае в какой-то момент вы увидите сообщения, выводимые на экран в процессе выполнения метода finalize . Если ни одного сообщения не появится, попробуйте увеличить число создаваемых объектов, изменив условие завершения цикла for.