Добавлен пример для finalize()
This commit is contained in:
parent
ae1ff3abbb
commit
6666fbb895
70
core.md
70
core.md
|
@ -773,12 +773,80 @@ __Пул строк__ – это набор строк хранящийся в _
|
|||
[к оглавлению](#java-core)
|
||||
|
||||
## Что такое `finalize()`? Зачем он нужен?
|
||||
Через вызов метода `finalize()` JVM реализуется функциональность аналогичная функциональности деструкторов в С++, используемых для очистки памяти перед возвращением управления операционной системе. Данный метод вызывается при уничтожении объекта сборщиком мусора (_garbage collector_) и переопределяя `finalize()` можно запрограммировать действия необходимые для корректного удаления экземпляра класса - например, закрытие сетевых соединений, соединений с базой данных, снятие блокировок на файлы и т.д.
|
||||
Через вызов метода `finalize()` (который наследуется от Java.lang.Object) JVM реализуется функциональность аналогичная функциональности деструкторов в С++, используемых для очистки памяти перед возвращением управления операционной системе. Данный метод вызывается при уничтожении объекта сборщиком мусора (_garbage collector_) и переопределяя `finalize()` можно запрограммировать действия необходимые для корректного удаления экземпляра класса - например, закрытие сетевых соединений, соединений с базой данных, снятие блокировок на файлы и т.д.
|
||||
|
||||
После выполнения этого метода объект должен быть повторно собран сборщиком мусора (и это считается серьезной проблемой метода `finalize()` т.к. он мешает сборщику мусора освобождать память). Вызов этого метода не гарантируется, т.к. приложение может быть завершено до того, как будет запущена сборка мусора.
|
||||
|
||||
Объект не обязательно будет доступен для сборки сразу же - метод `finalize()` может сохранить куда-нибудь ссылку на объект. Подобная ситуация называется «возрождением» объекта и считается антипаттерном. Главная проблема такого трюка - в том, что «возродить» объект можно только 1 раз.
|
||||
|
||||
Пример:
|
||||
```java
|
||||
public class MainClass {
|
||||
|
||||
public static void main(String args[]) {
|
||||
TestClass a = new TestClass();
|
||||
a.a();
|
||||
a = null;
|
||||
a = new TestClass();
|
||||
a.a();
|
||||
System.out.println("!!! done");
|
||||
}
|
||||
}
|
||||
```
|
||||
```java
|
||||
|
||||
public class TestClass {
|
||||
|
||||
public void a() {
|
||||
System.out.println("!!! a() called");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
System.out.println("!!! finalize() called");
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
```
|
||||
Так как в данном случае сборщик мусора может и не быть вызван (в силу простоты приложения), то результат выполнения программы с большой вероятностью будет следующий:
|
||||
```
|
||||
!!! a() called
|
||||
!!! a() called
|
||||
!!! done
|
||||
```
|
||||
Теперь несколько усложним программу, добавив принудительный вызов Garbage Collector:
|
||||
```java
|
||||
public class MainClass {
|
||||
|
||||
public static void main(String args[]) {
|
||||
TestClass a = new TestClass();
|
||||
a.a();
|
||||
a = null;
|
||||
System.gc(); // Принудительно зовём сборщик мусора
|
||||
a = new TestClass();
|
||||
a.a();
|
||||
System.out.println("!!! done");
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
Как и было сказано ранее, Garbage Collector может в разное время отработать, поэтому результат выполнения может разниться от запуска к запуску:
|
||||
Вариант а:
|
||||
```
|
||||
!!! a() called
|
||||
!!! a() called
|
||||
!!! done
|
||||
!!! finalize() called
|
||||
```
|
||||
Вариант б:
|
||||
```
|
||||
!!! a() called
|
||||
!!! a() called
|
||||
!!! finalize() called
|
||||
!!! done
|
||||
```
|
||||
|
||||
|
||||
[к оглавлению](#java-core)
|
||||
|
||||
## Что произойдет со сборщиком мусора, если выполнение метода `finalize()` требует ощутимо много времени, или в процессе выполнения будет выброшено исключение?
|
||||
|
|
Loading…
Reference in New Issue