Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / OutOfMemory и прочие неприятности для GUI / 20 сообщений из 20, страница 1 из 1
21.09.2007, 21:19:59
    #34819072
Турборуль
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Никак не могу понять, как защитить GUI приложение от проблем с глобальными сбоями типа OutOfMemory. Хочется чтобы такие сбои не приводили к непредсказуемому поведению приложения (типа застрелов), а просто позволить пользователю дождаться более удачного момента, чтобы выпполнить действие.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
 import  java.util.LinkedList;

 import  java.awt.FlowLayout;

 import  java.awt.event.ActionEvent;

 import  javax.swing.AbstractAction;
 import  javax.swing.JFrame;
 import  javax.swing.JButton;
 import  javax.swing.JOptionPane;
 import  javax.swing.SwingUtilities;

 public   class  Failure
 extends  JFrame
{
	 private  LinkedList garbage =  new  LinkedList();
	
	 private  Thread eater =  new  Thread()
	{
		 private   long  sleep =  1 ;
		
		 public   void  run()
		{
			 while  (true)
			{
				 try 
				{
					garbage.add( new   int [ 250 ]);
					sleep(sleep);
				}
				 catch  (InterruptedException e)
				{
					 super .interrupt();
					 break ;
				}
				 catch  (Throwable e)
				{
					// Не будем насиловать GC :)
					sleep =  10000 ;
				}
			}
			
			garbage.clear();
		}
	};
	
	 private  Thread.UncaughtExceptionHandler globalExceptionHandler =  new  Thread.UncaughtExceptionHandler()
	{
		 private   static   final  String errorText = "Out of memory!";
		
	     public   void  uncaughtException(
	        Thread t, 
	        Throwable e)
	    {
	    	// Здесь можно было бы создать диалог об ошибке, вместо этого сообщения в консоль
	    	System.out.println(errorText);
	    }
	};
	
	
	 public  Failure()
	{
		Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
		
		setLayout( new  FlowLayout());
		JButton buttonEat =  new  JButton( new  AbstractAction("Eat")
		{
			 public   void  actionPerformed(
				ActionEvent event)
			{
				((JButton) event.getSource()).setEnabled(false);
				eater.start();
			}
		});
		JButton buttonRelease =  new  JButton( new  AbstractAction("Release")
		{
			 public   void  actionPerformed(
				ActionEvent event)
			{
				eater.interrupt();
			}
		});
		
		JButton buttonTest =  new  JButton( new  AbstractAction("Test")
		{
			 public   void  actionPerformed(
				ActionEvent event)
			{
				// Должно привести к OutOfMemory, будет перехвачено в глобальном перехватчике
				JOptionPane.showMessageDialog(Failure. this , "Test");
			}
		});
		
		add(buttonEat);
		add(buttonRelease);
		add(buttonTest);
	}
	
	 public   static   void  main(
		String[] args)
	{
		SwingUtilities.invokeLater( new  Runnable()
		{
			 public   void  run()
			{
				Failure f =  new  Failure();
				f.pack();
				f.setLocationRelativeTo( null );
				f.setVisible(true);
			}
		});
	}
}

Однако в этом примере после запуска потока, сжирающего память не удается даже нажать на кнопку Release... после минуты усиленной работы GC приложение просто отстреливает JFrame, хотя джава машина продолжает работать...
...
Рейтинг: 0 / 0
24.09.2007, 10:57:36
    #34820747
vas0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
по моему когда прилетает OutOfMemory, тогда уже бесполезно с ней бороться. У тебя JVM захлебнулась и приложению кирдык. Нужно до этого просто не доводить и следить за тем чтобы ненужные объекты становились доступны для gc.
...
Рейтинг: 0 / 0
24.09.2007, 11:24:04
    #34820830
Juga
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
может -Xmx поможет отцу русской демократии, хотя это и не выход но иногда помогает, когда код уже вылизан.
...
Рейтинг: 0 / 0
24.09.2007, 16:20:16
    #34822016
Турборуль
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
vas0по моему когда прилетает OutOfMemory, тогда уже бесполезно с ней бороться. У тебя JVM захлебнулась и приложению кирдык. Нужно до этого просто не доводить и следить за тем чтобы ненужные объекты становились доступны для gc.

Проблема не в ненужных объектах, а в физическом недостатке памяти, который просто нужно временно пережить, не умерев на пути к светлому будущему :) Все-таки ОС, БД, разные сетевые сервисы не стреляются и не умирают при недостатке памяти, а просто временно отказывают в обслуживании, неужели это невозможно для ГУИ?
...
Рейтинг: 0 / 0
24.09.2007, 16:27:20
    #34822037
Leonidv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Никак. OutOufMemory Error возникает только если нет возможности найти память для объекта после выполнение сборщика мусора. Другими словами, сначала освобождается, что можется, и если после этого не хватает памяти - вызывается ошибка.
...
Рейтинг: 0 / 0
25.09.2007, 12:23:22
    #34823918
wessen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Все зависит от задачи, которую решает приложение. Если перед выполнением задачи возможно достаточно точно оценить, сколько потребуется памяти, то перед выполнением такой задачи можно посмотреть сколько места осталось в куче и если будет видно, что его не хватит для выполнения задачи, то не выполнять ее. Так делает JEdit к примеру, если попытаться им открыть очень большой файл, то он вывидит диалог в котором написано, что операцию выполнить невозможно и ссылка на мануал - как дать приложению больше памяти.
...
Рейтинг: 0 / 0
25.09.2007, 13:05:54
    #34824167
Timm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
1. OOM пролетает в eater thread, поэтому если надо поставить default exception handler, его надо ставить например при создании потока eater. При этом есессно не нужно ловить Throwable (это вообще дурной стиль).
2. Когда случится OOM, eater thread будет в состоянии terminated и вызов interrupted - что мертвому припарка.
3. "приложение просто отстреливает JFrame, хотя джава машина продолжает работать"
посмеялсо. RTFM
...
Рейтинг: 0 / 0
25.09.2007, 17:37:58
    #34825478
Турборуль
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Timm1. OOM пролетает в eater thread, поэтому если надо поставить default exception handler, его надо ставить например при создании потока eater. При этом есессно не нужно ловить Throwable (это вообще дурной стиль).

Вы не поняли как работает код. Eater thread постоянно доедает всю доступную память, поэтому я не хочу чтобы он завершался ни при каких условиях и ловлю Throwable (в т.ч. OutOfMemoryError), поймав который просто уменьшаю интенсивность сжирания памяти. Речь не идет о тоне и пр. сторонах программирования, представлен конкретный код, есть конкретная задача -- заставить его работать так, как он должен (по моему мнению) работать.

Timm
2. Когда случится OOM, eater thread будет в состоянии terminated и вызов interrupted - что мертвому припарка.

См. п. 1. eater thread никогда не будет в состоянии terminated.

Timm
3. "приложение просто отстреливает JFrame, хотя джава машина продолжает работать"
посмеялсо. RTFM
И кто же интересно вызывает close фрейма и с какого перепугу? Это типа нормальное поведение Swing'а закрывать фреймы когда ему вздумается?
...
Рейтинг: 0 / 0
25.09.2007, 17:41:20
    #34825494
Турборуль
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
wessenВсе зависит от задачи, которую решает приложение. Если перед выполнением задачи возможно достаточно точно оценить, сколько потребуется памяти, то перед выполнением такой задачи можно посмотреть сколько места осталось в куче и если будет видно, что его не хватит для выполнения задачи, то не выполнять ее. Так делает JEdit к примеру, если попытаться им открыть очень большой файл, то он вывидит диалог в котором написано, что операцию выполнить невозможно и ссылка на мануал - как дать приложению больше памяти.
Это было бы вариантом для монолитного приложения, но когда какой-то модуль начинает сжирать память (например из за ошибки программиста или ошибки пользователя -- запустил слишком сложную операцию), то я совершенно не хочу, чтобы данные в других модулях были потеряны.
...
Рейтинг: 0 / 0
25.09.2007, 19:11:16
    #34825762
Timm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Турборуль Timm1. OOM пролетает в eater thread, поэтому если надо поставить default exception handler, его надо ставить например при создании потока eater. При этом есессно не нужно ловить Throwable (это вообще дурной стиль).

Вы не поняли как работает код.
Это точно.
Твой код - memory leak. Выполняется операция, N раз, при этом расходуемая память планомерно растет после каждого выполнения, и не отдается. Выхода из _такой_ ситуации нет ни для обычных, ни для GUI-шных приложений, хоть гиг выдели, хоть два. рано или поздно все умрет.
...
Рейтинг: 0 / 0
26.09.2007, 00:48:09
    #34826149
wessen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Турборуль
Это было бы вариантом для монолитного приложения, но когда какой-то модуль начинает сжирать память (например из за ошибки программиста или ошибки пользователя -- запустил слишком сложную операцию), то я совершенно не хочу, чтобы данные в других модулях были потеряны.

memory leak это fatal error и никак иначе, такие баги в идеале должны отлавливаться на этапе тестирования и отладки, а ты так рассуждаешь, как-будто это обычное дело. и вообще, если возникает исключение, которое наследуется от Error, то JVM хана, она не в рабочем состоянии, ничего сделать уже нельзя, только restart. почитай вобщем java doc.
...
Рейтинг: 0 / 0
27.09.2007, 18:07:29
    #34832455
Турборуль
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
wessen Турборуль
Это было бы вариантом для монолитного приложения, но когда какой-то модуль начинает сжирать память (например из за ошибки программиста или ошибки пользователя -- запустил слишком сложную операцию), то я совершенно не хочу, чтобы данные в других модулях были потеряны.

memory leak это fatal error и никак иначе, такие баги в идеале должны отлавливаться на этапе тестирования и отладки, а ты так рассуждаешь, как-будто это обычное дело. и вообще, если возникает исключение, которое наследуется от Error, то JVM хана, она не в рабочем состоянии, ничего сделать уже нельзя, только restart. почитай вобщем java doc.

Т.е. то, что в c/c++ решается кодом
Код: plaintext
1.
2.
  garbage = malloc(n);
  if (!garbage) return E_OUT_OF_MEMORY;

в java решается перезапуском машины? Забавно... Почитал javadoc, но ничего похожего там не нашел.

Timm Турборуль Timm1. OOM пролетает в eater thread, поэтому если надо поставить default exception handler, его надо ставить например при создании потока eater. При этом есессно не нужно ловить Throwable (это вообще дурной стиль).

Вы не поняли как работает код.
Это точно.
Твой код - memory leak. Выполняется операция, N раз, при этом расходуемая память планомерно растет после каждого выполнения, и не отдается. Выхода из _такой_ ситуации нет ни для обычных, ни для GUI-шных приложений, хоть гиг выдели, хоть два. рано или поздно все умрет.

Зачем так прикапывать к тестовому примеру и вечно уходить с основной темы в сторону memory leak? Ну замените eater thread на следующий.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
 private  Thread eater =  new  Thread()
	{
		 public   void  run()
		{
                     try  {
		         int [] bigHeap =  new   int [очень много памяти];
		        // Сделать очень долгую, требующую много памяти (но не больше, чем уже выделено в bigHeap) работу в фоновом режиме
                     }
                      catch  (OutOfMemoryError)
                     {
                        // callback
                     }
		}
	};

Причем поток этот запускается в модуле, о существовании которого другие модули даже не догадываются.
...
Рейтинг: 0 / 0
27.09.2007, 18:19:37
    #34832499
Timm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Турборуль
Зачем так прикапывать к тестовому примеру и вечно уходить с основной темы в сторону memory leak? Ну замените eater thread на следующий.

Ни в коем случае не ухожу от темы. Пойми, что твой код _расходует память и не освобождает ее_
андестенд?
...
Рейтинг: 0 / 0
27.09.2007, 19:30:32
    #34832693
Турборуль
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Timm Турборуль
Зачем так прикапывать к тестовому примеру и вечно уходить с основной темы в сторону memory leak? Ну замените eater thread на следующий.

Ни в коем случае не ухожу от темы. Пойми, что твой код _расходует память и не освобождает ее_
андестенд?

Я заменил код на тот, который расходует и освобождает, что изменилось?
...
Рейтинг: 0 / 0
27.09.2007, 21:44:45
    #34832947
Leonidv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
http://www.devx.com/tips/Tip/5542
...
Рейтинг: 0 / 0
28.09.2007, 15:50:00
    #34835204
Timm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Турборуль Timm Турборуль
Зачем так прикапывать к тестовому примеру и вечно уходить с основной темы в сторону memory leak? Ну замените eater thread на следующий.

Ни в коем случае не ухожу от темы. Пойми, что твой код _расходует память и не освобождает ее_
андестенд?

Я заменил код на тот, который расходует и освобождает, что изменилось?
В чем проблема в измененном коде eater'a? я ее не вижу.
Еще раз:
"Хочется чтобы такие сбои не приводили к непредсказуемому поведению приложения "
такого поведения в общем случае обеспечить невозможно.
Какую то защиту можно организовать, если при старте приложения создать абсолютно все объекты которые понадобятся при обработке OOM и в обработке оперировать только ими. И то не во всех случаях поможет. лучше фиксить проблемы с памятью.
...
Рейтинг: 0 / 0
28.09.2007, 17:45:17
    #34835640
Турборуль
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Timm
В чем проблема в измененном коде eater'a? я ее не вижу.


В том, что если выделить достаточно много памяти, свинг застрелит фрейм, если кликнуть по кнопке.

Timm
Еще раз:
"Хочется чтобы такие сбои не приводили к непредсказуемому поведению приложения "
такого поведения в общем случае обеспечить невозможно.
Какую то защиту можно организовать, если при старте приложения создать абсолютно все объекты которые понадобятся при обработке OOM и в обработке оперировать только ими. И то не во всех случаях поможет. лучше фиксить проблемы с памятью.

Ок, тогда может лучше обсудить как реализуют такую защиту реальные приложения? Например, графические оболочки. Я не уверен насчет kde/gnome, так как редко их использовал, но винда точно не начинает закрывать окна при недостатке памяти и уж тем более не застреливает все на своем пути.
...
Рейтинг: 0 / 0
28.09.2007, 17:47:26
    #34835648
Турборуль
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Leonidvhttp://www.devx.com/tips/Tip/5542

1) это не вариант для многопоточных приложений
2) это не вариант для крупных приложений, не вставлять же такую проверку после каждой инструкции, которая что-то создает? Хочется универсальный удобный механизм типа UncaughtExceptionHandler.
...
Рейтинг: 0 / 0
28.09.2007, 17:48:12
    #34835650
Timm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
Турборуль Timm
В чем проблема в измененном коде eater'a? я ее не вижу.


В том, что если выделить достаточно много памяти, свинг застрелит фрейм, если кликнуть по кнопке.

1. версия JVM и ОС
2. параметры запуска
3. полностью код который к этому приводит.
Я такого не наблюдал.
...
Рейтинг: 0 / 0
28.09.2007, 18:11:13
    #34835726
1024
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
OutOfMemory и прочие неприятности для GUI
наверна у тебя не фрейм убивается а поток который забрал всю память. Т.е. весь AWT
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / OutOfMemory и прочие неприятности для GUI / 20 сообщений из 20, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]