1. What is the structure of the JVM?

A quick look at the MEMORY structure of the JVM shows that the memory in the JVM is divided into five virtual regions:

Heap – Every object allocated in your Java program needs to be stored in memory. The heap is where these instantiated objects are stored. Yes – blame the new operator for filling up your Java heap! Forced it Shared by all threads as much when the heap exhaustion, the JVM throws Java lang. An OutOfMemoryError forced the size of the heap can through the JVM options – Xms and -xmx to adjust

The heap is divided into: ▪ Eden region — new objects or objects with a short lifetime are stored in this region. The size of this region can be adjusted with the -xx :NewSize and -xx :MaxNewSize parameters. The new generation GC (garbage collector) will clean up this area. ▪ Survivor zone – Objects that still have references and survive the Eden zone garbage collection will stay in this zone. The size of this zone can be adjusted by the JVM parameter -xx :SurvivorRatio. ▪ Old age – Objects that have survived multiple GCS in Eden and Survivor zones (thanks, of course, to lingering references) are stored in this zone. This area will be handled by a special garbage collector. Collection of objects in the old generation is done by the old generation’s GC (Major GC). Method area ▪ also known as the non-heap area (in HotSpot JVM implementations) ▪ It is divided into two main sub-areas of persistent generation. This area stores class-related data including class definitions, structures, fields, methods (data and code), and constants. It can be adjusted by -xx :PermSize and -xx :MaxPermSize. If you run out of its space, can lead to Java. Lang. OutOfMemoryError: PermGen space. Code cache This cache area is used to store compiled code. The compiled code is native (hardware-dependent) code generated by the JIT (Just In Time) compiler, which is specific to the Oracle HotSpot JVM. JVM stacks ▪ closely related to methods in Java classes ▪ Stores local variables and intermediate results and return values of method calls ▪ Each thread in Java has its own stack that is inaccessible to other threads. ▪ Local stack can be adjusted via the JVM option -XSS ▪ PC registers assigned to local methods (non-Java code) ▪ A thread-specific program counter ▪ Contains the address of the instruction being executed by the JVM (its value is undefined in the case of local methods)

2. Why does the term permanent generation never appear in the JVM specification?

According to the JVM specification, THE JVM memory is divided into five parts: virtual machine stack, heap, method area, program counter, and local method stack:

The vast majority of Java programmers should have seen “Java. Lang. OutOfMemoryError: PermGen space” this exception. The “PermGen space” here actually refers to the method area. The former is a specification for the JVM, while the latter is an implementation of the JVM specification, and only HotSpot has a “PermGen space”, while there is no “PermGen space” for other types of virtual machines such as JRockit (Oracle), J9 (IBM). Because the method area mainly stores information about the class, it is easy to run out of memory of the permanent generation in the case of dynamically generated classes. The most typical scenario is that in the case of a large number of JSP pages or loaded packages, it is easy to run out of permanent generation memory. As a result, you will see that the Java8 virtual machine specification is no different from Java7, but everyone is telling you that the Hotspot virtual machine has abandoned the persistent generation.

3. Will persistent generations in JDK7 be recycled? What does it recycle?

Normal garbage collection does not occur in the permanent generation. If the permanent generation is full or the threshold is exceeded, a full garbage collection (FullGC) is triggered. If you look closely at the output from the garbage collector, you will see that the persistent generation is also reclaimed. So what does the permanent generation recycle? Deprecated string constants and class objects that are no longer referenced. Setting the permanent generation size correctly is a very important reason to avoid FullGC. So full GC can be caused not only by the old generation being full or exceeding the threshold, but also by the permanent generation being full or exceeding the threshold.

4. The permanent generation is gone. So how is HotSpot implemented in the JVM specification?

Hotspot in JDK8 uses Metaspace(Metaspace) instead of permanent generation. There are some changes compared to the permanent generation. This change is described in the following article: blogs.oracle.com/poonam/entr…

Among them was the following:

The meta space is allocated directly in local memory. The default metadata space allocation is limited only by local memory. We can use a new MaxMetaspaceSize option to set the amount of local memory that meta-space occupies. This option is similar to MaxPermSize. When the MetaspaceSize value is set (the default is 12M for 32-bit client mode, 16M for 32-bit server mode, and more for 64-bit server mode), the garbage collector collects classloaders and classes that are no longer used and are recycled. So setting a large MetaspaceSize value delays when garbage collection occurs. After a garbage collection is triggered and before the next one, the usage value of the meta-space increases with usage.

If you want to know more about meta-spaces, you can visit this link, which covers more details about meta-spaces.

5. What is the principle of Hotpsot garbage collection?

Hotspot’s garbage collection decisions are based on reachability analysis algorithms. In the mainstream implementation of current programming languages (Java,C#, etc.), it is called Reachability Analysis to determine whether objects survive. The basic idea of this algorithm is to search down from a series of objects called “GC Roots” as the starting point, and the search path is called the Reference Chain. When an object is not connected to GC Roots by any Reference Chain (in terms of graph theory, it is from GC When Roots detects that the object is unreachable, the object is not available. As shown in the figure below, object 5, Object 6, and Object 7 are related to each other, but they are not reachable to GC Roots, so they will be judged as recyclable objects.

It’s not enough just to know. On my blog, I have a translation of the JAVA Memory Whitepaper, which is very classic.

6. Will objects judged to be garbage sites always be recycled?

Even in the reachability analysis algorithm, unreachable objects are not necessarily dead. At this time, they are temporarily in the “probation” stage. In order to truly declare an object dead, at least two marking processes must be experienced: If an object is found to have no reference chain connected to GC Roots after the reachabality analysis, it will be marked for the first time and filtered based on whether it is necessary to execute the Finalize () method. When an object does not overwrite a Finalize () method, or a Finalize () method has already been called by a virtual machine, the virtual machine considers both cases “not necessary to execute”. (that means direct recycling)

If the object is determined to be necessary to finalize(), then the object will be placed ina Queue called f-Queue and executed later by a low-priority Finalizer thread automatically set up by the virtual machine. Here the so-called “execution” refers to the virtual chance to trigger this method, but not promised to wait for it to run over, the reason for this is that if an object in the finalize () method of slow execution, or the infinite loop (in the case of the more extreme), will likely result in a permanent in F – other objects in the Queue Queue waiting, even cause the whole The memory reclamation system crashes. Finalize () method is the last chance for objects to escape death. Later, GC will tag objects in the F-queue for a second time ina small scale. If objects want to save themselves from Finalize () successfully, they only need to re-associate with any object in the reference chain, such as themselves (this keyword). A member variable assigned to a class variable or object that is removed from the “collection to be collected” on the second tag; If the object hasn’t escaped at this point, it’s basically been reclaimed. Code examples:

public class FinalizeEscapeGC {
    public static FinalizeEscapeGC SAVE_HOOK = null;

    public void isAlive() {
        System.out.println("yes,i am still alive:)");
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize mehtod executed!");
        FinalizeEscapeGC.SAVE_HOOK = this;
    }

    public static void main(String[] args) throws Throwable {
        SAVE_HOOK = new FinalizeEscapeGC();
        // The object successfully saves itself for the first time
        SAVE_HOOK = null;
        System.gc();
        // Since the Finalize method has a low priority, we pause for 0.5 seconds to wait for it
        Thread.sleep(500);
        if(SAVE_HOOK ! =null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("no,i am dead:(");
        }
        // The following code is exactly the same as the above, but the self-rescue fails
        SAVE_HOOK = null;
        System.gc();
        // Since the Finalize method has a low priority, we pause for 0.5 seconds to wait for it
        Thread.sleep(500);
        if(SAVE_HOOK ! =null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("no,i am dead:("); }}}Copy the code

Running results:

finalize mehtod executed!
yes,i am still alive:)
no,i am dead:(Copy the code

The SAVE_HOOK object’s Finalize () method was indeed triggered by the GC collector and managed to escape before it was collected. Another noteworthy is that the code have two places are exactly the same code snippet, turned out to be a successful escape, a failure, this is because any object’s finalize () method will only be automatically call time, if the object facing the next recovery, its finalize () method will not be executed again, so the first Two pieces of code failed to save themselves. Because the Finalize () method has already been called by the virtual machine, the virtual machine considers it “unnecessary to execute” (that is, direct collection).