I bloom in the slaughter, like a flower in the dawn

— Embers

The opening words

With that in mind, we know that all objects are attached to something called a class, and both classes and objects are stored in the MEMORY of the JVM. This chapter will reveal the mystery of memory.

Runtime data area

During the execution of Java programs, the Java VIRTUAL machine divides the managed memory into different memory areas. These memory areas have different roles in the JVM, and the memory areas managed by the JAVA Virtual machine mainly include the following run-time data areas.!

Methods area

We talked about loading classes, so where does the information about those classes go? Yes, in our method area. The method area mainly stores the class information that has been loaded by the virtual machine, constants, static variables, code cache data compiled by the immediate compiler, etc. Of course, it’s thread shared, and for heap memory, it’s often referred to as “non-heap.”

Method area, meta-space, permanent generation

When it comes to method areas, we have to mention the relationship between method areas, permanent generations, and meta-spaces.

Methods area:

  • It is the design specification of the JVM. It is a logical thing that all virtual machines must obey. In fact, it is not comparable to the meta-space, permanent generation.
  • Is shared by all THREADS of the JVM and used to store class information that has been loaded by the virtual machine, constants, static variables, just-in-time compiled code cache data, etc

Permanent generation:

PermGen is a Permanent Generation space.

  • PermGen space is the HotSpot VIRTUAL machine’s landing implementation of the method area based on the JVM specification, and only HotSpot has PermGen space.
  • For example, JRockit (Oracle) and J9 (IBM) virtual machines have method areas, but no PermGen space.
  • PermGen space is a landing implementation of the method area for the HotSpot virtual machine in JDK7 and earlier. Removed in JDK8.

Dimension:

The biggest difference between a meta-space and a permanent generation is that the meta-space is not in virtual machine memory, but uses local memory.

  • Removing PermGen starts with JDK7. For example, string internals have been removed from permanent generations in JDK7. Until the release of JDK8 will spell the end of PermGen.
  • In fact, the removal of PermGen started in JDK7, and part of the permanent generation data (string constant pool) has been moved to the Java Heap or Native Heap.
  • However, persistent generations still exist in JDK7, not completely removed, for example:
    1. Literals (Interned strings) are transferred to the Java heap;
    2. Class statics are moved to the Java heap;
    3. Symbols are transferred to the Native heap;
    JDK version Method area implementation The location of the string constant pool
    JDK6 PermGen Space (Permanent Generation) PermGen Space (Permanent Generation)
    JDK7 PermGen Space (Permanent Generation) Heap (Heap)
    JDK8 Metaspace (meta-space) Heap (Heap)

In JDK6, JDK7, the method area is PermGen. In JDK8, the method area is Metaspace.

So let’s think about it, why do we replace permanent generations with metacreages?

Ostensibly to avoid OOM exceptions.

Because it is common to use PermSize and MaxPermSize to set the size of the permanent generation to determine the upper limit of the permanent generation, it is not always possible to know how appropriate it should be, and it is easy to get OOM errors if you use the default.

When using meta-space, the number of classes of metadata that can be loaded is no longer controlled by MaxPermSize, but by the actual available space on the system.

The deeper reason is to merge HotSpot and JRockit code, JRockit never had a so-called persistent generation, nor did it require development operations to set the size of the persistent generation, but it worked fine. There are also no performance issues to worry about. In the tests covered, the application was up and running less than 1% slower, but this performance penalty is worth more security.

  • Due to the permanent generation memory often enough or memory leaks occur, abnormal report Java. Lang. OutOfMemoryError: PermGen.
  • Strings exist in persistent generation, which is prone to performance problems and memory overflow.
  • It is difficult to determine the size of information about classes and methods, so it is difficult to specify the size of permanent generation. If the size is too small, it is easy to overflow the permanent generation, while if the size is too large, it is easy to overflow the old generation.
  • Persistent bit GC introduces unnecessary complexity and low collection efficiency.
  • Oracle may merge HotSpot and JRockit into one.

Heap (Heap)

For Java applications, the Java heap is the largest chunk of memory managed by the virtual machine, and the Java heap is the thread-shared area that is created when the virtual machine is started. The sole purpose of this area is to hold instances of objects, and almost all instances in Java are allocated in this heap memory.

Partition of heap memory

By default, the heap is divided into Cenozoic and old age in a ratio of 1:2 (not absolute, but slightly different), and the Cenozoic is divided into Eden: Survior From: Survior To by 8:1:1. The division of these regions is closely related to the garbage collector, and these divisions are based on classical generation design, which is not the case with some collectors, such as the G1 collector.

Escape analysis, allocation on the stack, scalar replacement (Understood)

Of course, if some objects have a small memory footprint, and they do not escape according to escape analysis, the object will be scalar replacement and allocated to the stack memory.

Escape analysis is generally divided into two kinds, one is method escape, the other is thread escape, for example, as a call parameter passed to other methods, this is called method escape; It can even be accessed by an external thread, such as assigning a value to an instance variable that can be accessed from another thread, called thread escape. Never escape, method escape to linear escape, called the object from low to high different degree of escape.

When a certain object meets the condition that it can be allocated on the stack, this part of the data will be allocated on the stack and destroyed as the stack frame is ejected from the stack.

Java virtual machine stack

The Java virtual machine stack is private to the program and its life cycle is synchronized with that of the thread. For each thread, there is a replicaManager local variable in the main() method. Therefore, the JVM must have an area for storing local variables and other data within each method. This area is the Java virtual machine stack

Each thread has its own Java virtual machine stack

When a thread does not call a method, it will form a stack frame, and when it calls, it will push the stack frame onto the stack, and when the method is finished, the stack frame will exit the stack.

The stack frame contains information about the method’s local variator, operand stack, dynamic linkage, method exit, and so on.

The local variable table stores various Java virtual machine basic data types (Boolean, byte, CHAR, short, int, float, long, double) and object references (reference type, which is not the same as the object itself) known at compile time. May be a reference pointer to the object’s starting address, a handle representing the object or other location associated with the object) and the returnAddress type (which points to the address of a bytecode instruction).

Local method stack

The role of Native Method Stacks is very similar to that of the virtual machine stack, except that the virtual machine stack performs Java methods (i.e. bytecodes) for the virtual machine, whereas the Native Method stack services the Native methods used by the virtual machine.

Program counter

The Program Counter Register is a small memory space that can be thought of as a line number indicator of the bytecode being executed by the current thread. In the conceptual model of Java virtual machine, the bytecode interpreter works by changing the value of this counter to select the next bytecode instruction to be executed. It is an indicator of program control flow, and basic functions such as branch, loop, jump, exception handling, thread recovery and so on need to be completed by this counter.

Because Java virtual machine multithreading is implemented by the way threads alternate and allocate processor execution time, at any given time, one processor (or kernel for multi-core processors) will execute instructions in only one thread. Therefore, in order to recover to the correct execution position after thread switching, each thread needs to have an independent program counter, which is not affected by each other and stored independently. We call this kind of memory area “thread private” memory.

If the thread is executing a Java method, this counter records the address of the virtual machine bytecode instruction being executed. If the Native method is being executed, this counter value should be null. This memory region is the only one where the Java Virtual Machine Specification does not specify any OutOfMemoryError cases.

Run-time constant pool

The run-time constant pool is stored in the method area. In addition to the magic number, version number, field, method, and interface descriptions, the Class file contains the constant pool table, which is used to generate various literals and symbolic references at compile time. This section is stored in the run-time constant pool of the method area after the Class is loaded.

Runtime constant pool relative to the Class file another important feature of the constant pool is dynamic, the Java language does not require constant Must only compile time to produce, that is to say, is not a preset constant pool into the Class file content can enter method area run pool, often during a run can also be new constants in the pool, One feature that developers use most often is the Intern () method of the String class.

Since the runtime constant pool is part of the method area and is naturally limited by the method area memory, OutOfMemoryError is thrown when the constant pool can no longer claim memory.

Compare Class file constant pools, runtime constant pools, and string constant pools based on JDK8

Class file constant pool:

In the Class file, it is the state before the runtime constant pool is parsed. The Class file information is stored in the method area, so the Class file constant pool is stored in the method area. Each class has this class file constant pool, which becomes a runtime constant pool once it’s parsed. It is static to the runtime constant pool and cannot be added dynamically.

Runtime constant pool:

Generated at the compile stage, it is stored in the method area. Each class has a run-time constant pool. The so-called run-time constant pool is actually put the compiled class information into an area of the runtime, used to dynamically obtain the class information.

Run-time constant pooling is the dumping of symbolic references from each class constant pool to the run-time constant pool after the class is loaded. That is, each class has a run-time constant pool. After the class is parsed, symbolic references are replaced with direct references, consistent with the reference values in the global constant pool.

String constant pool:

In JDK1.7, the string constant pool was slowly moved from the method area to the heap memory. Before that it was stored in the permanent generation (method area).

Constant pool and string constant pool version changes

Prior to JDK1.7, the runtime constant pool logic contained string constant pools stored in the method area, where the hotspot virtual machine implemented the method area as a permanent generation

In JDK1.7 the string constant pool is taken from the method area to the heap, there is no mention of the runtime constant pool, that is, the string constant pool is taken to the heap separately, what is left of the runtime constant pool is still in the method area, which is the permanent generation in hotspot

In JDK1.8 hotspot, Metaspace was removed. The string constant pool is still in the heap, and the runtime constant pool is still in the method area, but the method area implementation is changed from permanent generation to Metaspace.

String.intern() the difference between JDk1.6 and Jdk1.7
A detailed analysis

So what is this intern for? In JDK1.6 and before that, the intern method checks whether the constant exists in the constant pool and returns a reference to the current constant. If it does not, the intern method copies the constant to the constant pool and returns its reference address. After the JDK 1.7, intern method will still go to inquire whether there is already exists in the constant pool, if present, return the reference in the constant pool, before this and there is no difference, the difference is that, if the constant pool can’t find the corresponding string, is can’t again copies a string into a constant pool, but only in the constant pool to generate a reference to the original string. In simple terms, what is put into the constant pool is changed: if it is not found in the constant pool, make a copy of it and put it into the constant pool. After 1.7, copy the address reference on the heap into the constant pool.

Next, I mainly analyzed JDK1.7 with an Intern. Then, I looked at several online cases and problems that have been rotten in the streets.

** Case 1

String a1 = new String("abcd");
String a2 = "abcd";
System.out.println(a1 == a2);
System.out.println(a1 == a1.intern());
System.out.println(a2 == a1.intern());
Copy the code

Q: In the above code, will the string abcd be generated in the constant pool? Is the final output true or false?

A: Look at the screenshot below

The JVM creates a String in the heap, determines whether the String abcd exists in the String constant pool, if not, stores the String in the String constant pool, and if so, assigns the abCD reference from the constant pool to the String in the heap.The result returns false,false, true. The first false is because A1 points to the String in the heap and A2 points to the reference in the constant pool. The second false is because the string abcd already exists in the constant pool, so a1. Intern () should be equal to a2.

Case 2.

String a1 = new String("abcd") + new String("efgh");
String a2 = a1.intern();
String a3 = "abcdefgh";

System.out.println(a1 == a2);
System.out.println(a1 == a3);
System.out.println(a2 == a3);
Copy the code

Q: What is the memory distribution and what data is stored in the constant pool? What does the output look like?

A: First, after executing the first line of code, there are abcd and efgh strings in the constant pool, but abcdefgh is not in the constant pool. There is an instance of abcdefgh in the heap (it is not in the constant pool yet). Then execute a1. Intern (); = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh = abcdefgh;

From the above analysis, it can be seen that the output results are true, true, true respectively. These three values are actually the heap memory address of A1 (reference address).

Case 3.

String a1 = new String("abcd") + new String("efgh");
String a3 = "abcdefgh";
String a2 = a1.intern();

System.out.println(a1 == a2);
System.out.println(a1 == a3);
System.out.println(a2 == a3);
Copy the code

Note: The difference between case 3 and Case 2 is that the position of A3 is switched with that of A2. The same question is asked. A: Final output is false,false,true; After executing the first line of code, there is a string abcdefgh in the heap, but this string does not exist in the constant pool. A1 refers to the instance in the heap. A3 refers to the string abcdefgh in the string constant pool, and a2 (a1.intern()) returns the string abcdefgh already exists in the string constant pool, so a2 is actually equal to A3 but not equal to A1.

String s=new String(” ABC “) how many objects are created?

If there is no “ABC” in the constant pool before the statement String s=new String(” ABC “) is executed, then a String constant is created in the constant pool when creating new String(), and then a new String is created in the heap from that String constant. But both string objects (” ABC “in the constant pool and” ABC “in the heap) have the same array of underlying characters.

If the String constant “ABC” is available before execution (as in the code above), only one object will be created in the heap when String s=new String(” ABC “) is executed.

Verify that “ABC” in the constant pool and “ABC” in the heap are the same array of underlying characters

In the String constructor, the “ABC” object created in the heap with the new keyword and the “ABC” object in the constant pool are not the same, but the underlying array of the two objects is the same.

We use reflection to modify the underlying array of String objects in the constant word to see if the String in the heap changes as well:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { // String s1 = new String("a") ; // //String s3 = "a"; // System.out.println(s1.intern() == s1); String str2 = new String(" ABC "); String str2 = new String(" ABC "); //str2.intern(); String str = "abc"; / / get the String class value Field in the Field, the Field = String. Class. GetDeclaredField (" value "); // Set the field to an accessible field.setaccessible (true); Char [] arr = (char[]) field.get(STR); arr[2]='1'; System.out.println(str); // Output: ab1 system.out.println (str2); // Output: ab1 // system.out.println (a3 == a1. Intern ()); //true // System.out.println(a3.intern() == a1); //false }Copy the code

Analysis again:

Without this line, STR points to abCABC in the heap, and str2 points to ABCABC in the string constant pool. With this line, both STR and str2 are references to STR2 (because that’s what the constant pool holds). So the same thing, if you change one of them, you change both of them

Direct memory:

Direct Memory is not part of the run-time data area of the virtual machine, nor is it defined in the Java Virtual Machine Specification. However, this portion of memory is also frequently used and can cause OutOfMemoryError exceptions

conclusion

This chapter is mainly about how the Java runtime data areas, just about, the author mainly in that a few other constant pool contrast, the Internet also has a lot of data, but there are a lot of is wrong, I hope you find some comparison on the spectrum data, I also look for a long time, dizzy, but slowly understand think this version is right. The intern method is a bit disgusting, because different JDK versions lead to unexpected implementation results, hope you can understand. Finally, I hope you can watch the officer, if there is wrong place, please also be able to point out, common learning, progress!

I like this line of EMBER very much, on behalf of the new life after suffering, refueling everyone