What happens when we new an object? Here’s some code:
public class Tested {
public static int T = 10;
public int c = 1;
}
Copy the code
Class initialization
At compile time, the compiler converts the Tested. Java class into the Tested. Class bytecode file. When a VIRTUAL machine receives the new bytecode instruction, the virtual machine initializes the class first if the class has not already been initialized.
After the class is loaded. The virtual machine allocates memory in the Java heap for the Tested object of new Tested(). The amount of memory an object needs is determined after the class is loaded.
Pointer to the collision
If memory in Java is neat, the used ones are placed on one side and the free ones on the other, with Pointers in between as indicators of the cut-off point. The memory allocated is simply to move the pointer as free space by a distance equal to the size of the object. This method is called pointer collision.
The free list
If memory in Java is untidy, with used and free memory interleaved, the virtual machine must maintain a list of what memory is available. At allocation time, find a large enough space from the list for the object sample, and update the table records. This type of allocation is called a free list.
Object initialization
When our object memory is allocated, the virtual machine initializes the object.
At this point, the Tested object is born in our eyes, but is actually usable in the eyes of the virtual machine. But an object’s life is not infinite, and it will experience its own death.
Accessibility analysis
In mainstream implementations, we use reachability analysis to determine whether an object is alive or not. The idea is: through a series of objects called “GC Roots” as the starting point, the search starts from these nodes. The path of the search is called the reference chain. When an object is not connected to GC Roots by any reference chain, it is proved that the object is not available. As shown in figure:
Even if Obj5 and Obj4 are not linked by reference to GC Roots, we call GC Roots unreachable to Obj4 and Obj5. So Obj4 and Obj5 are recyclable.
Since Obj4 and Obj5 are recyclable, will they necessarily be recycled? Not necessarily. At this point, the virtual machine performs the marking process for the first time. Because you can override finalize() in Java (this is just a special case, it is not recommended to use it in any case), when the object overwrites finalize(), and finalize() has not been called by the virtual machine, the virtual machine will put the object into a special F-queue. A separate Finalizer thread executes it. If the Finalize () method of objects in the queue is executed before the virtual machine is tagged for the second time and connects itself to the GC Roots reference chain during the second tag, then the virtual machine is tagged for the second time. The object is removed from the f-queue, otherwise it is declared dead. Note: The Finalize () method is executed only once, so an object has only one chance in its lifetime to get into an F-queue and escape death.
If the object is declared dead, how does the virtual machine reclaim it?
Mark-clear algorithm
This is the most basic collection algorithm, which is divided into two phases: mark and clear. First mark all the objects that need to be recycled, after the completion of all marked objects are recycled. Refer to the free list above. It has two disadvantages:
A. Efficiency problem. Both marking and clearing processes are inefficient.
B. Space problems, because the memory in the heap is not tidy, used and free memory are interlocked, which leads to a large amount of memory fragmentation after each GC collection, and when allocating a large object again, if not enough contiguous memory can be found, the GC collection will be triggered again.
Replication algorithm
The copy algorithm divides the heap into two equal pieces and uses only one piece at a time, so that the memory is tidy and the reference pointer collides. Whenever a block of memory is used up, the living objects in that block are copied to the other side, and then the block is cleaned up once.
Today’s virtual machines recycle the new generation in this way, but instead of dividing memory in a 1:1 ratio, they divide memory into a large Eden space and two smaller Survivor Spaces (Eden: Survivor = 8:1 by default for HotSpot virtual machines). Only Eden and one Survivor space are used at a time. When reclaimed, Eden space and surviving objects in the currently used Survivor space are copied to another free Survivor space, and Eden and the Survivor memory that was just used are emptied.
Note: There is an overflow risk because there is no guarantee that each surviving object will always occupy less than Survivor memory. So in the generation collection algorithm, the virtual machine first divides the memory into a new generation memory and an old generation memory. In the new generation memory, this 8:1:1 memory allocation is used. If overflow occurs, all surviving objects in this situation are put in the old memory, which is a bottom-of-the-pocket strategy. The important thing to note here is that not the part of the overflow, but all the living objects.
Mark-collation algorithm
The marking process in the mark-tidy algorithm is the same as that in the mark-clear algorithm. The difference is that after the marking and cleaning and recycling of objects are completed, the current discontinuous fragmented memory will be sorted out, that is, the surviving objects will be moved to one end to ensure the regularness of the memory to be allocated next. This algorithm is used in our generation collection algorithm for old memory blocks (of course, it can also be mark-clear algorithm, different strategies for different virtual machines). So I don’t need to talk about the generational collection algorithm.
Well, that’s the end of the “object” life cycle. If this article is useful to you, give it a thumbs up. Everyone’s affirmation is also the motivation for Dumb I to keep writing.
1. Zhou Zhiming, Understanding JAVA Virtual Machines in Depth: China Machine Press