官术网_书友最值得收藏!

Finalization

Finalization is a process of releasing resources. It's executed with a finalizer method that's invoked after an object becomes unreachable, but before its memory is deallocated. Finalization is a non-deterministic process because it's not known when garbage collection will occur, and it might never happen. This is in contrast to a destructor, which is a method called for finalization in languages with manual memory management.

The following diagram illustrates the simplified life cycle of an object:

A destructor, in most languages, is the language-level term that means a method defined in a class by a programmer. A finalizer is an implementation-level term that means a method called by a system during object creation or destruction. Finalizers are needed to perform object-specific operations, cleaning or releasing resources that were used with an object. That's why they're most frequently instance methods.

Finalizers have several drawbacks:

  • It may never be called promptly, so a software engineer cannot rely on it to do something important, such as persisting a state or releasing scarce resources.
  • The invoking order of finalizers isn't specified.
  • Garbage collection, and consequently the finalizer, runs when memory resources are terminated but not when it's time to release other scarce resources. So, it's not a good idea to use it to release limited resources.
  • If too much work is performed in one finalizer, another one may start with a delay. And this may increase the total time of the garbage collection pause.
  • A finalizer may cause synchronization issues as well because it can use shared variables.
  • A finalizer in a superclass can also slow down garbage collection in a subclass because it can refer to the same fields.

To implement the finalizer in Java, a developer has to override the finalize() method of the Object class. The Object class has an empty implementation of the following method: 

protected void finalize() throws Throwable { }

This method has good documentation with two interesting moments. The first is that the Java programming language doesn't guarantee which thread will invoke the finalize() method for any given object. It's guaranteed, however, that the thread that invokes the finalize() method will not be holding any user-visible synchronization locks when finalize() is invoked. If an uncaught exception is thrown by the finalize() method, the exception is ignored, and finalization of that object terminates. And the second interesting catch is that any exceptions that are thrown by the finalize() method cause the finalization of this object to be halted, but they are otherwise ignored.

A sample of overriding can be found, for instance, in the source code of the FileInputStream class:

@Override protected void finalize() throws IOException {
try {
if (guard != null) {
guard.warnIfOpen();
}
close();
} finally {
try {
super.finalize();
} catch (Throwable t) {
// for consistency with the RI, we must override Object.finalize() to
// remove the ’throws Throwable’ clause.
throw new AssertionError(t);
}
}
}

This implementation ensures that all resources for this stream are released when it's about to be garbage collected.

But in Kotlin, the root of the class hierarchy is Any, which does not have a finalize() method:

public open class Any {

public open operator fun equals(other: Any?): Boolean

public open fun hashCode(): Int

public open fun toString(): String
}

But according to the Kotlin documentation: https://kotlinlang.org/docs/reference/java-interop.html#finalize, to override finalize(), all you need to do is simply declare it without using the override keyword (and it can't be private):

class C {
protected fun finalize() {
// finalization logic
}
}

If you read to avoid finalizers and cleaners item of the effective Java book, you know that using finalizers to release resources is a common anti-pattern. To acquire resources in the constructor or initialization block and release it in the finalizer isn't a good approach. It's better to acquire the resources only when needed and release them once they're no longer needed. In other cases, using the finalize() method to release resources can cause resource and memory leaks.

主站蜘蛛池模板: 烟台市| 苏尼特右旗| 黄冈市| 大同县| 韶关市| 秦皇岛市| 安岳县| 布尔津县| 城市| 巨野县| 汪清县| 连城县| 嫩江县| 上思县| 武汉市| 广德县| 昔阳县| 钟山县| 黎平县| 栾城县| 满洲里市| 美姑县| 鹰潭市| 锡林浩特市| 鹤峰县| 平昌县| 赤水市| 丁青县| 正定县| 大兴区| 韶关市| 静海县| 泾阳县| 勐海县| 花垣县| 扬州市| 日喀则市| 咸宁市| 乌鲁木齐县| 潮州市| 正镶白旗|