17 августа 2019 года    
Суббота | 16:57    
Главная
 Новости
Базы данных
Безопасность PC
Всё о компьютерах
Графика и дизайн
Интернет-технологии
Мобильные устройства
Операционные системы
Программирование
Программы
Связь
Сети
 Документация
Статьи
Самоучители
 Общение
Форум







Разделы / Программирование / Java

А где же память?

А где же память?


О некоторых особенностях работы сборщика мусора (garbage collector, gc) в Sun JDK 1.2.2 и IBM JDK 1.3.0.


Как известно, сборщик мусора в виртуальной Ява-машине - это параллельный процесс с низким приоритетом. Он выполняется одновременно с программой пользователя и добавляет к свободной памяти участки хипа, на которые никто не ссылается. Возникает резонный вопрос - что будет, если программа начнет интенсивно выделять память на относительно короткий срок? Успеет ли сборщик мусора "вычистить мусор"?
Рассмотрим следующий пример (он должен находиться в файле TestGC.java):

class Elem
   {
   								int h[];
   	Elem() { h = new int[100000]; }
   	public void finalize()	{ System.out.print("finalize() "); }
   }
   public class TestGC
   {
 public static void Oops() throws Exception {
     throw new Exception("Test");
    }
 public static void main(String[] arg) {
    	int dummy = 1;
     	for (int i = 0; i < 100000; i++)
     	{
     		try {
     			Elem elem;
     			elem = new Elem();
     			if (dummy == 1) Oops();
    		}
     		catch(Exception e) {
   //  			System.gc();
     			System.out.print("" + i + " ");
     		}
     	}
    }
   }

В примере в цикле происходит выделение нового экземпляра объекта Elem (размером около 400 Кбайт). Сразу после этого "бросается" исключение и мы, разумеется, теряем указатель на этот новый объект. Следуя логике java этот объект тут же превращается в "мусор", который следует "чистить". Откомпилируем данный пример и запустим его с ограничением размера динамической памяти 20 Mb.
Это делается так :

java -Xms1Mb -Xmx20Mb TestGC

Под Sun JVM можно наблюдать следующее поведение: через какое-то время происходит исключение OutOfMemory (нехватка памяти). Под IBM JVM такого не происходит. Объяснение этому может быть такое: в случае, когда при выделении памяти ее не хватает, IBM JVM приостанавливает все процессы и принудительно вызывает сборщик мусора. Тот высвобождает память, достаточную для нового объекта и программа продолжает выполнение. Это очень разумное поведение, которое и ожидаешь в данном случае. Для Sun JVM дела обстоят не так радостно. Очевидно, что Sun JVM не пытается особым образом обработать случай нехватки памяти и для программ, интенсивно использующих память, остается один выход - самим вызывать сборщик мусора (System.gc()) в критических местах. Если откомментарить строчку с данным вызовом в вышеуказанном примере, то поведение программы становится абсолютно предсказуемым - сразу после появления "мусора", он "вычищается". Можно так же устанавливать и ожидание треда через sleep, тогда при нехватке памяти gc() все таки будет вызываться. В противном случае главный тред не даст выполниться треду gc() и возникнет исключение о нехватке памяти.

 А где же память?
Лента новостей


2006 (c) Copyright Hardline.ru