Simply understand the garbage collection mechanism of Java and the function of finalize method

When the garbage collector wants to recycle objects, it must first call the finalize method of this class (you can write a program to verify this conclusion). Generally, classes written in pure java do not need to overwrite this method, because the object has implemented a default, unless we want to implement special functions (there are many things involved, such as object space tree, etc.). However, for classes written in code other than Java (such as JNI, the memory allocated by the new method of C + +), the garbage collector cannot correctly recycle these parts. At this time, we need to override the default method to release and recycle this part of memory correctly (for example, delete is required for C + +). In short, finalize is equivalent to a destructor. It is the first method to be called when the garbage collector recycles an object. However, because Java's garbage collection mechanism can automatically do these things for us, we generally do not need to release them manually.

Sometimes when you undo an object, you need to do something. For example, if an object is dealing with non Java resources, such as file handles or window character fonts, make sure that these resources are released before an object is revoked. To deal with this situation, Java provides a mechanism called finalization. Using this mechanism, you can define some special operations that are executed when an object is about to be released by the garbage collector. To add a finalizer to a class, you just need to define the finalize () method. This method is called when Java reclaims an object of this class. In the finalize () method, you specify the actions that must be performed before an object is undone. Garbage collection runs periodically, checking that objects are no longer referenced by running state or indirectly through other objects. Just before the object is released, the Java runtime system calls the finalize () method of the object.

The general format of the finalize () method is as follows:

The keyword protected prevents code defined outside the class from accessing the finalize () identifier. This and other identifiers will be explained in Chapter 7.

It is important to understand that finalize () is called just before garbage collection. For example, when an object is out of its scope, finalize () is not called. This means that you cannot know when -- or even if -- finalize () is called. Therefore, your program should provide other methods to release system resources used by objects, rather than relying on finalize() to complete the normal operation of the program.

Note: if you are familiar with C + +, you know that C + + allows you to define an Undo function for a class, which is called just before the object is out of scope. Java does not support this idea and does not provide Undo functions. The finalize () method is only close to the function of Undo functions. When you have rich experience in Java, you will see that because Java uses the garbage collection subsystem, there is little need to use Undo functions.

The working principle of finalize should be as follows: once the garbage collector is ready to release the storage space occupied by the object, it first calls finalize (), and only in the next garbage collection process will it really reclaim the memory of the object So if you use finalize (), you can do some important cleaning or cleaning during garbage collection

When is finalize () called? There are three situations

In addition, normally, when an object is collected as useless information by the system, finalize () will be called automatically, but the JVM does not guarantee that finalize () will be called, that is, the call of finalize () is uncertain, which is why sun does not advocate the use of finalize ()

Sometimes when you undo an object, you need to do something. For example, if an object is dealing with non Java resources, such as file handles or window character fonts, make sure that these resources are released before an object is revoked. To deal with this situation, Java provides a mechanism called finalization. Using this mechanism, you can define some special operations that are executed when an object is about to be released by the garbage collector.

To add a finalizer to a class, you just need to define the finalize () method. This method is called when Java reclaims an object of this class. In the finalize () method, you specify the actions that must be performed before an object is undone. Garbage collection runs periodically, checking that objects are no longer referenced by running state or indirectly through other objects. Just before the object is released, the Java runtime system calls the finalize () method of the object.

The general format of the finalize () method is as follows:

The keyword protected prevents code defined outside the class from accessing the finalize () identifier. This and other identifiers will be explained in Chapter 7.

It is important to understand that finalize () is called just before garbage collection. For example, when an object is out of its scope, finalize () is not called. This means that you cannot know when -- or even if -- finalize () is called. Therefore, your program should provide other methods to release system resources used by objects, rather than relying on finalize() to complete the normal operation of the program.

Note: if you are familiar with C + +, you know that C + + allows you to define an Undo function for a class, which is called just before the object is out of scope. Java does not support this idea and does not provide Undo functions. The finalize () method is only close to the function of Undo functions. When you have rich experience in Java, you will see that because Java uses the garbage collection subsystem, there is little need to use Undo functions.

During garbage collection, the garbage collector will automatically call the finalize method of the object to perform some user-defined non memory cleaning, because the garbage collector will not handle things outside memory. Therefore, sometimes users need to define some cleaning methods, such as processing non memory resources such as files and ports.

1. GC overview of JVM GC, that is, garbage collection mechanism, refers to the memory used by the JVM to release objects that are no longer used. The Java language does not require the JVM to have GC, nor does it specify how GC works. However, most commonly used JVMs have GC, and most GC use similar algorithms to manage memory and perform collection operations. After fully understanding the garbage collection algorithm and execution process, we can effectively optimize its performance. Some garbage collection is dedicated to special applications. For example, real-time applications are primarily designed to avoid garbage collection interruptions, while most OLTP applications focus on overall efficiency. After understanding the workload of the application and the garbage collection algorithm supported by the JVM, you can optimize the configuration of the garbage collector. The purpose of garbage collection is to clean up objects that are no longer used. GC determines whether to collect an object by determining whether it is referenced by an active object. GC first determines whether the object is ready for collection. Two common methods are reference counting and object reference traversal.      1.1. Reference count reference count stores the number of all references to a specific object, that is, when the application creates a reference and the reference is out of range, the JVM must increase or decrease the number of references appropriately. When the number of references of an object is 0, garbage collection can be performed.      1.2. Object reference traversal early JVMs used reference counting, but now most JVMs use object reference traversal. Object reference traversal starts with a group of objects and follows each link on the whole object graph, Recursively determines reachable objects. If an object cannot reach from one (at least one) of these root objects, it is garbage collected. In the object traversal phase, GC must remember which objects can reach in order to delete unreachable objects. This is called marking (marking) objects. Next, GC will delete unreachable objects. When deleting, some GCS simply scan the stack, delete unmarked and unmarked objects, and free their memory to generate new objects, which is called cleanup The problem with this method is that the memory is divided into many small segments, which are not enough for new objects, but the combination is large. Therefore, many GC can reorganize the objects in memory and compress them (compact) to form an available space. For this purpose, GC needs to stop other activities. This method means that all application related work stops and only GC runs. As a result, many mixed requests are added or deleted during the response. In addition, more complex GC increases or runs at the same time to reduce or clear the interruption of the application. Some GC make Use a single thread to complete this work, and some use multithreading to increase efficiency.    2. Several garbage collection mechanisms 2.1 Mark - clear collector. This collector first traverses the object graph and marks reachable objects, and then scans the stack to find unmarked objects and free their memory. Such collectors typically work with a single thread and stop other operations.      2.2. The mark compression collector is sometimes called Mark clear compression collector, which has the same marking stage as the mark clear collector. In the second stage, the marker object is copied to a new field of the stack to compress the stack. This collector also stops other operations.      2.3. Copy collector this collector divides the stack into two domains, often referred to as half space. Only half of the space is used at a time, and the new objects generated by the JVM are placed in the other half. When GC runs, it copies reachable objects to the other half of the space, compressing the stack. This method is suitable for short-lived objects, and continuous replication of long-lived objects leads to reduced efficiency.      2.4. Incremental collector the incremental collector divides the stack into multiple domains and collects garbage from only one domain at a time. This can cause minor application interruptions.      2.5. Generational collector this collector divides the stack into two or more domains to store objects with different lifetimes. The new objects generated by the JVM are usually placed in one of the domains. Over time, objects that continue to exist will gain useful life and move into longer-lived domains. Generational collectors use different algorithms for different domains to optimize performance.      2.6. Concurrent collectors concurrent collectors run simultaneously with applications. These collectors are at some point (such as compression) generally have to stop other operations to complete specific tasks, but because other applications can perform other background operations, the actual time to interrupt other processing is greatly reduced. 2.7. Parallel collector parallel collector uses a traditional algorithm and uses multi threads to execute their work in parallel. In multi CP Using multithreading technology on u machine can significantly improve the scalability of Java applications.

3. Destruction process of objects

In the process of destroying an object, it can be divided into the following types according to the execution of the object's finalize. The system will record the corresponding status of the object: unfinalized does not execute finalize, and the system is not ready to execute. The system will execute finalize at a later time. Finalized the object's finalize has been executed.

How can GC keep track of finalizable objects. GC has a queue called f-queue. All objects will be added to the queue when they become finalized, and then wait for GC to execute its finalize method.

At this time, we introduce another record classification of objects. The system can check which kind of object belongs to. Reachable refers to the objects reachable by the chain from the active object. Including local variables of the current stack of all threads, all static variables, etc. Finalizer reachable in addition to reachable, objects that can be reached from the f-queue by reference. Unreachable other objects.

Let's look at the state transition diagram of the object.

It's so big and dizzy. Take your time.

First of all, all objects are on the road from reachable + unfinalized to death.

2 when the object is unreachable from the current active set, the object can change from reachable state to f-reachable or unreachable state.

3 when the object is non reachable + unfinalized, the GC will move it into the f-queue and the state will change to f-reachable + finalized.

4 well, here's the key. At any time, GC can get a finalized object from f-queue, mark it as finalized, and then execute its finalize method. Because the object is reachable again in this thread, So the object becomes reachable (and finalized). When the finalize method is executed, it is possible to change other f-reachable objects into a reachable, which is called object regeneration.

5 when an object is unreachable + unfinalized, if the object uses the default object's finalize, or although it is rewritten, the new implementation does nothing. For performance, the GC can change the objects to the reclaimed state and destroy them directly without adding them to the f-queue for further processing by the GC.

6. It can be seen from the state diagram that no matter how tossed, the finalize of any object is only executed once at most. Once the object becomes finalized, it will never return to the f-queue. Of course, there is no chance to perform finalize again.

7 when the object is unreachable + finalized, the object is not far from the real death. GC can safely reclaim the memory of the object. Enter reclaimed.

Examples of object regeneration

Expected output

However, it may fail due to the uncertainty of GC and timing problems. Running more times should be successful. See the reference document at the end of the text for a detailed explanation.

3.1 execution sequence of object finalize

The finalize execution of all finalizable objects is uncertain, neither which thread executes nor the order of execution. Consider the following situation to understand why instances a, B and C are a set of finalizable objects that are circularly referenced to each other.

3.2 when and how to use finalize

From the above analysis, the following conclusions are drawn. (1) Most importantly, try not to use finalize. It's too complicated. It's better to let the system take care of it. You can define other methods to release non memory resources. (2) if you use it, try to be simple. (3) if you use it, avoid object regeneration. This is to make trouble for yourself. (4) It can be used to protect non memory resources from being released. Even if we have defined other methods to release non memory resources, others may not call this method to release them. In finalize, you can check that if there is no release, it is better to release them later than not. (5) Even if the finalize of the object has been run, it cannot be guaranteed that the object will be destroyed. To implement some actions to ensure that the object is completely destroyed, we can only rely on the interaction between the class in java.lang.ref and GC.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>