Tag: Value post instruction error LSP remaining space application/tmp font
First, the JVM memory model
According to the JVM specification, the JVM memory is divided into five parts: virtual machine stack, heap, method area, program counter, local method stack.
1. Virtual machine stack: Each thread has a private stack that is created as the thread is created. In the stack is a kind of "stack frame" thing, each method will create a stack frame, the stack frame contains the local variable table (basic data type and object reference), operand stack, return address and other information. The size of the stack can be fixed (compile-time OK) and can be dynamically expanded. When the stack call depth is greater than the scope allowed by the JVM, it throws a stackoverflowerror error, but this depth range is not a constant value, and we can test the result with this program:
Stack Overflow test Source:
?
1234567891011121314151617181920 |
package com.paddx.test.memory;
public class StackErrorMock {
private static int index =
1
;
public void call(){
index++;
call();
}
public static void main(String[] args) {
StackErrorMock mock =
new StackErrorMock();
try {
mock.call();
}
catch (Throwable e){
System.out.println(
"Stack deep : "
+index);
e.printStackTrace();
}
}
}
|
Code Snippet 1
Run three times, you can see the depth of each stack is not the same, the output is as follows .
As for the value of the red box is how to come out, you need to go deep into the JVM source code can be explored, here does not elaborate.
Virtual machine Stack In addition to the above error, there is another error, that is, when the application is not space, will throw outofmemoryerror. Here's a small detail to note that catch captures are throwable, not Exception. Because Stackoverflowerror and outofmemoryerror do not belong to Exception subclasses.
2. Local method Stack:
This part is mainly related to the Native method used by the virtual machine, and in general, the Java application does not need to care about this part of the content.
3. PC Register:
PC registers, also called program counters. The JVM supports multiple threads running at the same time, each with its own program counter. If the JVM is currently executing a method, the address of the current execution instruction is saved in the register, and if the native method is executed, the PC register is empty.
4. Heap
Heap memory is a part of the JVM that is shared by all threads and is created when the virtual machine is started. All objects and arrays are allocated on the heap. This part of the space can be reclaimed by GC. OutOfMemoryError is thrown when there is no space to apply. Below we simply simulate a heap memory overflow scenario:
?
12345678910111213141516171819202122 |
package com.paddx.test.memory;
import java.util.ArrayList;
import java.util.List;
public class HeapOomMock {
public static void main(String[] args) {
List<
byte
[]> list =
new ArrayList<
byte
[]>();
int i =
0
;
boolean flag =
true
;
while (flag){
try {
i++;
list.add(
new byte
[
1024 *
1024
]);
//每次增加一个1M大小的数组对象
}
catch (Throwable e){
e.printStackTrace();
flag =
false
;
System.out.println(
"count="
+i);
//记录运行的次数
}
}
}
}
|
Code Snippet 2
Run the above code and the output is as follows:
Note that here I specify the heap memory size is 16M, so this place shows the count=14 (this number is not fixed), as to why it is 14 or other numbers, you need to judge according to the GC log
5. Method Area:
The method area is also shared by all threads. It is mainly used for storing class information, Chang, method data, method code and so on.
Second, HotSpot VM
In the process of learning the JVM, the most confusing concept is the partition of the memory area in the JVM specification and the partition of the JVM memory area in the JVM implementation, there is a mapping between them, the following is in different JDK versions of the hotspot Specific implementation of VMS (more detailed on Oracle's website JDK realse notes):
In JDK6 and previous versions of the Hotspot VM, the GC heap consisted of Young+old+perm Gen, where Young+old Gen would only store Java objects so it would certainly belong to the JVM's conceptual Java Heap; perm Gen has a mix of some Java objects and metadata that should belong to method area (class data, method data, symbols, and so on), so the Perm Gen is said to be a method area, which is not the same as part of the Java heap-- It is a mixture of the two.
In JDK7 's hotspot VM, the symbols (symbol reference) belonging to the method area was moved to the native heap and no longer in the GC heap; Field moved to the end of the Java.lang.Class object instance and was placed in Young+old Gen. As a result, Young+old Gen cannot say that it is purely Java heap, but also stores some data belonging to method area.
In the hotspot VM where JDK8 started, the Perm Gen was removed, and the metadata (class data, method data, etc.) belonging to the method area was also moved to the native heap. There is only static field in the data of method area that is in the GC heap.
?
1234 |
package com.paddx.test.memory; public class Test { } |
Code Snippet 3
?
12345678910111213141516171819202122232425 |
package com.paddx.test.memory;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
public class PermGenOomMock{
public static void main(String[] args) {
URL url =
null
;
List<ClassLoader> classLoaderList =
new ArrayList<ClassLoader>();
try {
url =
new File(
"/tmp"
).toURI().toURL();
URL[] urls = {url};
while (
true
){
ClassLoader loader =
new URLClassLoader(urls);
classLoaderList.add(loader);
loader.loadClass(
"com.paddx.test.memory.Test"
);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
|
Code Snippet 4
The results of the operation are as follows:
The JDK version used in this example is 1.7, and the size of the specified PermGen area is 8M. By loading the test class each time a different URLClassLoader object is generated, a different class object is generated so that we can see the familiar "Java.lang.OutOfMemoryError:PermGen space" exception. JDK 1.7 is used here because, in JDK 1.8, the HotSpot has no "PermGen space" and is replaced by something called metaspace (meta space). Let's take a look at the difference between Metaspace and PermGen space.
Three, metaspace (yuan space)
From the above, the removal of the permanent generation has started from JDK1.7. In JDK1.7, portions of data stored in a permanent generation have been transferred to the Java heap or to the Native heap. But the permanent generation still exists in JDK1.7, not completely removed, such as the Symbolic Reference (Symbols) transferred to the native heap, the literal (interned strings) and the class static variable (class Statics) transferred to Young+old Gen. We can compare the differences between JDK 1.6 and JDK 1.7 and JDK 1.8 in a program, with string constants as an example:
?
12345678910111213141516 |
package com.paddx.test.memory;
import java.util.ArrayList;
import java.util.List;
public class StringOomMock {
static String base =
"string"
;
public static void main(String[] args) {
List<String> list =
new ArrayList<String>();
for (
int i=
0
;i< Integer.MAX_VALUE;i++){
String str = base + base;
base = str;
list.add(str.intern());
}
}
}
|
This program continuously generates new strings at 2 exponential level, which makes it possible to consume memory more quickly. We run through JDK 1.6, JDK 1.7, and JDK 1.8, respectively:
Results of JDK 1.6 operation:
Results of JDK 1.7 operation:
Results of JDK 1.8 operation:
As you can see from the above results, there is a memory overflow of "PermGen Space" under JDK 1.6, and in JDK 1.7 and JDK 1.8, there is a heap memory overflow, and permsize and MaxPermGen in JDK 1.8 are not valid. Therefore, it is possible to roughly verify that JDK 1.7 and 1.8 transfer string constants from a permanent generation to a heap, and that there is no longer a permanent generation in JDK 1.8. Now let's see what the meta-space really is.
The nature of meta-space is similar to permanent generation, which is the implementation of the method area in the JVM specification. However, the biggest difference between meta-space and permanent generation is that the meta-space is not in the virtual machine, but rather uses local memory. Therefore, by default, the size of the meta-space is limited only by local memory, but you can specify the size of the meta-space by using the following parameters:
-xx:metaspacesize, the initial space size, which will trigger a garbage collection to type unload, and the GC will adjust the value: If a large amount of space is freed, the value is appropriately lowered, and if very little space is released, then when no more than maxmetaspacesize , raise the value appropriately.
-xx:maxmetaspacesize, the maximum space, the default is unlimited.
In addition to the above two specified size options, there are two GC-related properties:
-xx:minmetaspacefreeratio, after GC, the minimum amount of metaspace remaining space is reduced to the garbage collection caused by allocated space
-xx:maxmetaspacefreeratio, after GC, the maximum amount of metaspace remaining space is reduced to the garbage collection caused by free space
Now we rerun code Snippet 4 under JDK 8, but this time no longer specifies PermSize and MaxPermSize. Instead, specify the size of the metaspacesize and maxmetaspacesize. The output results are as follows:
From the output, we can see that this time there is no permanent overflow, but there is a meta-space overflow.
Iv. Summary
Through the above analysis, you should understand the JVM's memory division, also clear the JDK 8 in the conversion of the permanent generation of meta-space. But everyone should have a question, why do you want to do this conversion? So, finally, we summarize the following several reasons:
1, the string exists in the permanent generation, prone to performance problems and memory overflow.
2, classes and methods of information, such as difficult to determine its size, so the size of the perpetual generation is difficult to specify, too small prone to permanent overflow, too large will easily lead to old age overflow.
3, the permanent generation will bring unnecessary complexity to the GC, and the recovery efficiency is low.
4. Oracle may merge hotspot with JRockit.
JAVA8 memory Model-Permanent generation (PermGen) and meta-space (Metaspace) (RPM)