1 source

  • Source: Java Virtual Machine JVM Fault Diagnosis and Performance Optimization — Ge Yiming
  • Chapter: Chapter 4

This article is some notes of chapter 4.

2 GCalgorithm

Common GC algorithms include:

  • Reference counting method
  • Mark clearance
  • Replication algorithm
  • Label compression
  • Generational algorithm
  • Partitioning algorithm

2.1 Reference counting method

Implementation principle:

  • For an object A
  • Whenever any object references A, A’s reference counter is incremented by one
  • When a reference is invalid, the reference counter is decayed by 1
  • As long as object A’s reference counter has A value of 0, object A is no longer in use, waiting to be reclaimed

Disadvantages:

  • Circular references cannot be handled, such as A referring to B and B referring to A, but there is no other object referring to both. In this case, neither A nor B has A reference count of 0 and cannot be collected
  • Reference counters require that each reference is generated and eliminated with an addition operation and a subtraction operation, which has a certain impact on system performance

Reference counting is not used as a GC algorithm in Java due to the shortcomings described above.

2.2 Mark removal method

Tag removal divides garbage collection into two phases:

  • Marking phase: All reachable objects from the root node are marked through the root node. Unmarked objects are garbage objects
  • Clear phase: Clears all unmarked objects

Marking stage:

After the clearance:

The disadvantages are obvious, that is, the reclaimed space is discontinuous, and the efficiency will be lower than the continuous memory space.

2.3 Replication Algorithm

Core ideas:

  • The memory space is divided into two equal pieces
  • Use only one piece at a time
  • When collecting, live objects are moved to another block, and then all objects in the block in use are cleared
  • Swap the roles of two memory blocks

The advantage is that the reclaimed memory space is defragmentation free, while the disadvantage is that if there are a large number of objects, it takes a lot of time to copy and only has half of the original memory.

For example, in the following figure, A and B have the same memory space. During garbage collection, A copies living objects to B, and B remains continuous after replication:

After the replication is complete, A is cleared and B is set to the current space.

The replication algorithm is used in the new-generation serial garbage collector of Java. The new-generation serial garbage collector is divided into Eden zone, FROM zone and TO zone. The FROM and to areas are two Spaces with the same memory, also known as survivor area, also known as survivor space. At the time of garbage collection, the surviving objects in Eden and FROM will be copied to to, and then the FROM and Eden will be cleared. Then the roles in FROM and TO will be swapped, and the next garbage collection will be copied from the original TO (new from) to the original FROM (new TO).

2.4 Mark compression method

Tag compression method is a kind of old s algorithm, on the basis of marker QingChuFa did some optimization, and tags QingChuFa, also need to begin from the root node, first of all to do a tag object, and then all live objects to one end of the memory, then clean up all the space outside the boundary, here is as follows:

The advantage of tag compression is that it avoids fragmentation and does not require two identical memory Spaces.

2.5 Generational algorithm

Generational algorithm is not a specific garbage collection algorithm, but actually a different garbage collection algorithm according to the characteristics of each memory space to improve efficiency. Such as:

  • In the New generation: a large number of new objects are quickly recycled, so the new generation is better suited to using the copy algorithm
  • In the old days: mark compression or mark clearance

2.6 Partitioning Algorithm

Partition algorithm divides the whole heap space into continuous different cells, and each cell is used and recycled independently, as shown in the figure:

3 Four kinds of citations

Java provides four levels of references:

  • Strong reference
  • Soft references
  • A weak reference
  • Phantom reference

Let’s take a look at each of them.

3.1 strong reference

A strong reference is the type of reference commonly used in code. Strongly referenced objects are touchable and not recycled, for example:

StringBuffer str = new StringBuffer("a");
Copy the code

If the above code were to run inside the method body, the local variable STR would be allocated on the stack, and the object StringBuffer instance would be allocated on the heap. STR refers to the heap where the StringBuffer instance resides, and can be manipulated by STR. STR is a strong reference to an instance of StringBuffer.

For example, the following code is executed:

StringBuffer str1 = str;
Copy the code

Str1 also points to the same object that STR points to, that is, they both point to the same StringBuffer instance, in which case str1== STR is true because they both point to the same heapspace address.

The characteristics of strong references are as follows:

  • You can access the target object directly
  • Strong references to objects are not collected by the system,JVMWould rather throwOOMIt also does not reclaim objects to which strong references point
  • Strong references can cause memory leaks

3.2 soft references

Soft references are weak references that are strongly referenced. If an object holds only soft references, it will be reclaimed when the heap space is insufficient. Soft references can be implemented using the SoftReference class, as shown in the following code:

public static void main(String[] args){
    Byte[] b = new Byte[1024*1024*8];
    SoftReference<Byte[]> softReference = new SoftReference<>(b);
    b = null;
    System.out.println(softReference.get());
    System.gc();
    System.out.println("After GC");
    System.out.println(softReference.get());
    b = new Byte[1024*1024*8];
    System.gc();
    System.out.println(softReference.get());
}
Copy the code

On OpenJDK 11.0.10, adding -XMx40m produces the following output:

[Ljava.lang.Byte;@1fbc7afb
After GC
[Ljava.lang.Byte;@1fbc7afb
null
Copy the code

As you can see, soft reference objects are not necessarily collected when garbage is collected, but when memory is tight, soft reference objects are collected.

3.3 a weak reference

Weak references are weaker than soft references. During garbage collection, objects will be reclaimed as long as weak references are found, regardless of system space usage. However, because garbage collector threads are usually of low priority, weak reference objects are not always found quickly, in which case they can persist for a long time. Examples of weak references are as follows:

public static void main(String[] args){
    Byte[] b = new Byte[1024*1024*8];
    WeakReference<Byte[]> softReference = new WeakReference<>(b);
    b = null;
    System.out.println(softReference.get());
    System.gc();
    System.out.println("After GC");
    System.out.println(softReference.get());
}
Copy the code

Output (-XMx40m) :

[Ljava.lang.Byte;@1fbc7afb
After GC
null
Copy the code

As you can see, weak reference objects are reclaimed immediately after GC.

A common use scenario for soft references and weak references is to store unnecessary cache data. When the system memory is low, the cache data will be reclaimed without OOM, and when the system memory is sufficient, the cache data can be stored for a long time, thus speeding up the system.

3.4 virtual reference

Virtual references are the weakest of all reference types, and an object holding a virtual reference is almost the same as an object without a reference and can be collected by the garbage collector at any time. In addition, attempts to get strong references using the get() method of virtual references always fail, and virtual references need to be used with reference queues to track garbage collection.

public static void main(String[] args) throws Exception {
    ReferenceQueue<String> queue = new ReferenceQueue<>();
    PhantomReference<String> reference = new PhantomReference<>(new String("test"),queue);
    System.out.println(reference.get());
}
Copy the code

Output result:

null
Copy the code