Java Управління ресурсами

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Як я помітив, багато, початківці програмувати на Java, не цілком чітко уявляють собі, як варто управляти ресурсами на цій мові. У даній статті я спробував викласти своє бачення на цей аспект програмування.

Що може, а чого не може GC.

Одним з особливостей мови Java є автоматичне прибирання сміття - горезвісний Garbage Collector (скорочено - GC). GC - це фоновий процес, який займається пошуком та звільненням невикористовуваних об'єктів. Багато списів було зламано в дискусіях, добре це чи погано, причому суттєві аргументи є як у прихильників, так і у противників цієї технології. Але я не про це. Приймемо існування GC як даність і розглянемо особливості програмування в даному середовищі.

Одним з наслідків наявності GC (і відсутності розміщення об'єктів в стеку) є відсутність деструкторів, аналогічним існуючих в C + + - автоматично викликаються методів для знищення об'єктів по виходу з області видимості. Замість них є інші механізми, які дозволяють домогтися того ж самого.

Іншим наслідком є ​​необхідність стежити за посиланнями на об'єкти, тому як GC саме по наявності посилання на об'єкт визначає його потрібність. Для можливості управління строгістю посилань у JDK 1.2 був введений новий пакет java.lang.ref, класи якого дозволяє створювати так звані "слабкі" посилання на об'єкти. Це особливо корисно для реалізації кешування об'єктів.

Начитавшись рекламних статей, може здатися, що очищенням ресурсів взагалі не варто займатися - все зробить GC. Тут важливо розуміти, що в поняття ресурсів входить не лише оперативна пам'ять, але так само і багато іншого. Наприклад - відкриті файли, сокети, ResultSet-и і Statement-и в JDBC, і т.д. З очищенням пам'яті GC в останніх JVM справляється досить непогано, але от звільнення інших ресурсів, як правило, не можна робити асинхронно. В іншому випадку легко отримати так звані "плаваючі" помилки, які то з'являються, то зникають.

Над розробкою алгоритму роботи GC досить довго корпіли розробники, так що іноді його поведінка може здатися дещо дивним. Зокрема, він може звільняти об'єкти в довільному порядку, ніяк не пов'язаному з порядком їх створення або очищення останніх посилань на них. Так само, для прикладу, в JDK 1.3, GC починає звільняти об'єкти тільки тоді, коли поточний пул пам'яті заповнюється. При цьому одночасно, цей пул розширюється, поки не дійде до заданого верхнього ліміту. Одночасно враховується час останнього доступу і розмір об'єкта. І т.д. і т.п.

За замовчуванням верхній ліміт пулу залежить від системи. У JDK 1.3 він дорівнює 64 мегабайтам. У деяких випадках краще знизити цю планку, особливо коли на машині пам'яті не дуже багато - тим самим програма швидше дійде до цього ліміту і почне використовувати пам'ять повторно.

Більшість JVM не віддають назад системі пам'ять, яку вони забрали під пул. Я знаю тільки одну JVM, яка це робить - це Microsoft JVM. Всі інші хапає до зазначеного ліміту.

Деструкторів немає. А що замість?

Багато програмістів (особливо тільки що пересіли з C + +), бачать заміну деструкторів у вигляді методів finalize. Це не є правильно. По-перше, цей метод не зголоситься, поки на об'єкт є посилання. Немає гарантії, що він зголоситься тоді, коли вам це потрібно. Він може взагалі ніколи не викликатися. Є, звичайно, метод System.runFinalizersOnExit (), але він вже давно dedivcated через можливі deadlock-ів. Як справедливо зауважив Bruce Eckel в чудовій книжці Thinking in Java метод finalize варто використовувати тільки для того, щоб звільнити пам'ять (або інший, не дуже критичний ресурс), виділену в native методах. Для інших же ресурсів слід додати явний виклик методу очищення ресурсів (він може називатися по-різному - close, dispose, cleanup, і т.д.), усередині конструкції finally. Усередині finally - для того, щоб не прогавити якесь виключення. Приклад типових конструкцій:

OutputStream out = new FileOutputStream (...);

try

{

...

}

finally {out.close ();}

PreparedStatement stmt = ...;

try

{

stmt.setInt (1 ,...);

ResultSet rs = stmt.executeQuery ();

try

{

...

}

finally {rs.close ();}

}

finally {stmt.close ();}

Якщо Ви будете писати програми в такому стилі, то багато проблем обійдуть Вас стороною - повірте, я вже наступав на ці граблі. :-)

Memory Leak в Java і як з ним боротися.

Здавалося б - які можуть бути Memory Leak (витоку пам'яті), коли є GC. Але, тим не менш, вони можливі. Ці витоку відрізняються за своїм походженням від витоків в C / C + + (таких в Java взагалі бути не може, за винятком можливих помилок в JVM, але цей варіант ми тут не розглядаємо). Вони виникають через забутих посилань.

Наприклад - в GUI часто використовується механізм слухачів (Listener-ів). Це коли один об'єкт реєструється в іншому об'єкті для зворотного виклику по настанню якого-небудь події. Проблема тут може бути одна - якщо Ви забудете разрегістріровать об'єкт, коли він стає непотрібним. При цьому він залишиться бовтатися в списку, ну і GC, зрозуміло, не буде видаляти цей об'єкт, поки не прийде час видалити об'єкт зі списком (а цього може і не трапитися до завершення програми).

У результаті - список буде пухнути, пухнути, програма працює все повільніше і повільніше, і, врешті-решт, вилітає OutOfMemoryError.

Відстежити такий сценарій можна за допомогою спеціальних програм - профайлер. Найвідоміші на даний момент - JProbe і OptimizeIt.

Боротися з цими речами досить просто - треба не забути разрегістріроваться. Якщо Ви впевнені, що об'єкт-слухач видаляється разом з об'єктом - джерелом подій (наприклад, коли вони обидва сидять усередині діалогу), то цього робити не потрібно - GC сам з ними розбереться.

Кешування об'єктів.

Кешування об'єктів застосовується для підвищення продуктивності. Коли об'єкт змінюється рідко (або взагалі не змінюється в процесі роботи програми), то часто корисно прочитати його один раз, і запам'ятати на нього посилання. Але посилання - це протиріччя між алгоритмом роботи GC, а значить, цей об'єкт ніколи не буде зібраний GC (навіть якщо він більше не потрібний). Іноді це великого значення не має (пам'яті багато, або всі об'єкти потрібні дуже часто), але частіше бажано все-таки мати можливість почистити невикористовувані об'єкти.

У JDK 1.2 для цих цілей було додано кілька класів, найбільш цікаві з них - WeakReference і SoftReference. Weak ("слабка") посилання буде очищена, якщо на об'єкт немає більш "сильних" посилань і об'єкт попався під руку GC. Soft ("м'яка") посилання буде очищена, якщо на об'єкт немає звичайних посилань, і, до об'єкту не доступалісь за цим посиланням певний час (евристично розраховується в залежності від поточного оточення). Для кешування найкраще підходять посилання типу Soft, тому що в них враховується частота звернення до об'єкта.

Безпосередньо користуватися цими посиланнями не дуже зручно, краще написати контейнер з їх використанням. Ось, наприклад реалізація класу SoftHashtable:

import java.lang.ref.SoftReference;

import java.util.Hashtable;

public class SoftHashtable extends Hashtable

{

public SoftHashtable () {}

public Object put (Object key, Object obj)

{

SoftReference ref = (SoftReference) super.put (key, new SoftReference (obj));

if (ref == null) return null;

return ref.get ();

}

public Object get (Object key)

{

SoftReference ref = (SoftReference) super.get (key);

if (ref == null) return null;

return ref.get ();

}

public Object remove (Object key)

{

SoftReference ref = (SoftReference) super.remove (key);

if (ref == null) return null;

return ref.get ();

}

}

Цей клас є неповним, при бажанні Ви можете перекрити інші методи Hashtable. За допомогою цього класу Ви вже можете легко організувати свій кеш об'єктів:

private static Hashtable objCache = new SoftHashtable ();

public SuperObject getObject (String key)

{

SuperObject o = (SuperObject) objCache.get (key);

if (o == null)

{

o = loadObject (key);

objCache.put (key, o);

}

return o;

}

Таким чином, якщо GC виявить, що пам'яті залишилося мало, а в кеші бовтаються об'єкти, до яких давно ніхто не звертався, він зможе їх почистити.

Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Реферат
14.8кб. | скачати


Схожі роботи:
Управління людськими ресурсами 3
Управління трудовими ресурсами 2
Управління ресурсами та запасами
Управління людськими ресурсами 4
Управління людськими ресурсами
Управління людськими ресурсами 2
Управління розподіленими ресурсами
Управління трудовими ресурсами
Управління людськими ресурсами 5
© Усі права захищені
написати до нас