Поколения. Завершение и раскручивание стека.
Чтобы оптимизировать технологию, каждому объекту, находящемуся в управляемой динамически распределяемой области памяти, назначается поколение. Так, новому объекту назначается поколение 0, и такой объект рассматривается в качестве главного кандидата для сборки мусора. Ранее созданные объекты назначаются поколению 1. Поскольку такие объекты уже просуществовали некоторое время, есть вероятность, что их время жизни будет более продолжительным, чем у объектов поколения 0. Еще более старым объектам назначается поколение 2. Считается, что вероятность пережить сборку мусора у них еще больше. Максимальный номер поколения в текущей реализации .NET равен 2. Это число может быть взято из свойства GC::MaxGeneration.
Обычно сборщик мусора "выметает" только поколение 0. Именно в этом поколении находятся наиболее вероятные кандидаты на освобождение памяти. Все объекты поколения 0, пережившие сборку мусора, переходят в поколение 1. Если освобожденной памяти недостаточно, будут "выметены" объекты поколения 1, а выжившие будут продвинуты в поколение 2. Ну а затем, в случае необходимости, будут "выметены" и объекты поколения 2 и так далее вплоть до MaxGeneration – максимального количества поколений.
Завершение и раскручивание стека
Как было упомянуто ранее, одно из достоинств механизма обработки исключений заключается в том, что, поскольку при обработке исключения происходит раскрутка стека вызовов, локальные объекты выходят из области видимости и таким образом помечаются для завершения. Простая иллюстрация этого имеется в программе FinalizeStackUnwind. В этой программе используется рассмотренный ранее класс SimpleLog, в котором реализуется завершение.
//FinalizeStackUnwind.h using namespace System; // использование пространства имен Система; using namespace System::Threading; // использование пространства имен // Система::Организация поточной обработки; public _gc class FinalizeStackUnwind // класс сборщика мусора FinalizeStackUnwind { public: static void Main() { try { SomeMethod(); } catch(Exception *e) // Исключение { Console::WriteLine(e › Message); // Сообщение } GC::Collect(); // СБОРЩИК МУСОРА:: Собрать() Thread::Sleep(100); // Поток:: Бездействие } private: // частный static void SomeMethod () { // локальная переменная SimpleLog *alpha = new SimpleLog("alpha.txt"); // вызвать исключение throw new Exception("error!!"); // новое Исключение ("ошибка!!"); } };
SomeMethod выделяет место для локальной переменной-указателя alpha (алфавитный) типа SimpleLog*. Перед нормальным завершением метода, из него вызывается исключение. Механизм раскручивания стека при обработке особых ситуаций видит, что переменная-указатель alpha (алфавитный) больше не доступна, и помечает ее для сборки мусора. Вызов GC::Collect (Сборщик мусора::Собрать) приводит в действие сборку мусора, и мы видим в выдаче программы, что завершение действительно выполнено.
logfile alpha.txt created error!! logfile alpha.txt finalized logfile alpha.txt disposed
Перевод такой:
системный журнал alpha.txt создан ошибка!! системный журнал alpha.txt завершен системный журнал alpha.txt освобожден