JVM study notes (d) heap memory

6. heap memory model

6.1 Overview and illustrations

A non-heap, a heap area.

Reactor divided into two blocks, one old region, a region is Young.

Young divided into two blocks, one Survivor areas (S0 + S1), a region is Eden. Eden: S0: S1 = 8: 1: 1

As large as S0 and S1, may also be called From and To.

Diagram

 

Q: create an object in that area?

 

6.2 Object Creation area

Under normal circumstances, the object created will be assigned to the Eden area, some special large objects are assigned to the Old District.

For example there are objects A, B, C, etc. needs to be created in the Eden area, Eden initial size of 100M, if has been used 100M or reaches an upper limit, this time need to clean up the memory Eden area to clean up, i.e., garbage collection (Garbage Collect) such GC we call Minor GC, Minor GC refers to Young's GC.

After GC clean up, some objects will be cleaned up, some objects will survive, live objects need to be replicated with Survivor areas, then clean out the object Eden area.

6.3 Survivor Detailed Area

Seen from the illustration, Survivor divided into two S0 and S1, may also be called the From and To.

At the same time point, S0 and S1 can have a data area, and the other is empty.

The above is followed by GC, such as a start region and Eden From data area, To is empty.

At this time, to conduct a GC operation, From the age of an object area will be + 1, Eden zone live objects are copied to the To field,

Form zone can survive the object has two places.

  • Provided good age threshold before the age reached if the object, the object will be moved at this time to the area Old

  • If Form Eden region and not reach the threshold region of the object will be copied to the To field

At this Eden area and Form region it has been emptied.

At this time the roles were reversed From and To, before From-> To, To-> From.

That is, no matter what time in an area called To ensure Survivor is empty.

Minor GC would have been repeatedly performing such process until the To field is filled, then copy all objects to the Old District.

6.4 Old District Detailed

As can be seen from the above analysis, the general area of ​​Old Age are relatively large objects or objects more than a certain threshold.

Old district will have a GC operation, we call Major GC or Full GC.

6.5 Object of understanding life

I am an ordinary Java objects, I was born in the Eden area, Eden District, there are many like me junior partner, some parents will take them out of Eden area, some grew up with me, until one day, Eden District so many people there, we moved to the area From Survivor district From district since gone, I have been of no fixed abode, in the Survivor's "From zone" and "to zone" wandering back and forth. Until I was 18 years old of age, go out battles battles.

So I came to the Old District, a lot of people here, the age of relatively large, I lived for 20 years (GC time plus one year of age), and then recovered.

 

6.6 Frequently Asked Questions

  • How to understand the Minor / Major / Full GC

Minor GC : 新生代
Major GC :老年代
Full GC : 新生代+老年代
  • Why do we need Survivor areas? Only Eden district will not do it?

为了减少被送到 Old区的对象,进而减少 Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代存活的对象,会被送到 Old区。
  • Why do we need two Survivor areas?

最大好处就是解决了碎片化问题。假设只有一个S区,模拟下流程:
新建的对象在Eden区中,一旦Eden满了,出发 Minor GC,Eden中存活的对象就会被移动到 Survivor区。这样循环下去,下次Eden满了,问题来了,此时进行MinorGC,Eden和Survivor各存活了一些对象,如果强行将存活对象移动到Survivor 区,两部分对象所占有的空间是不连续 ,就会导致内存碎片化,浪费内存空间。
所以永远有一个Survivor space 是空的,另一个非空的S区 无碎片。
  • The new generation of Eden: S1: Why S2 is 8: 1: 1?

因为新创建的对象基本上是“朝生夕死”的。所以Eden区的内存分配占比比较高。
新生代中的可用内存:复制算法来担保内存为9:1
可用内存中Eden:S1区为8:1
即新生代Eden:S1:S2 = 8:1:1

 

6.7 Experience and verification

6.7.1 Use jvisualvm View

Download the plug Address: https://visualvm.github.io/pluginscenters.html

 

6.7.2 Heap memory overflow

Code demonstrates

Set runtime parameters -Xmx20M -Xms20M

@RestController 
public class HeapController { 
  List<Person> list=new ArrayList<Person>(); 
   
 @GetMapping("/heap") 
  public String heap() throws Exception{ 
    while(true){ 
        list.add(new Person()); 
        Thread.sleep(1); 
        } 
    } 
}
​

result

Exception in thread "http-nio-8080-exec-2" java.lang.OutOfMemoryError: GC overhead limit exceeded

6.7.3 Method memory overflow area

Class method to add information to the area

Add dependencies asm

<dependency>
  <groupId>asm</groupId> 
  <artifactId>asm</artifactId> 
  <version>3.3.1</version> 
</dependency>

Code

public class MyMetaspace extends ClassLoader { 
  public static List<Class<?>> createClasses() { 
    List<Class<?>> classes = new ArrayList<Class<?>>(); 
    for (int i = 0; i < 10000000; ++i) { 
      ClassWriter cw = new ClassWriter(0); 
      cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null, 
      "java/lang/Object", null); 
      MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", 
      "()V", null, null); 
      mw.visitVarInsn(Opcodes.ALOAD, 0); 
      mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", 
      "<init>", "()V"); 
      mw.visitInsn(Opcodes.RETURN); 
      mw.visitMaxs(1, 1); 
      mw.visitEnd(); 
      Metaspace test = new Metaspace(); 
      byte[] code = cw.toByteArray(); 
      Class<?> exampleClass = test.defineClass("Class" + i, code, 0, code.length); 
      classes.add(exampleClass); 
    }
    return classes; 
  } 
}
​

Access category

@RestController 
public class NonHeapController { 
  List<Class<?>> list=new ArrayList<Class<?>>(); 
  @GetMapping("/nonheap") 
  public String nonheap() throws Exception{ 
  while(true){ 
  list.addAll(MyMetaspace.createClasses()); 
  Thread.sleep(5); 
  } 
} 
}

Metaspace size setting, such as -XX: MetaspaceSize = 50M -XX: MaxMetaspaceSize = 50M

operation result

java.lang.OutOfMemoryError: Metaspace 
  at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_191]
  at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_191]

6.7.4 virtual machine stack overflow

public class StackDemo { 
  public static long count=0; 
  public static void method(long i){ 
    System.out.println(count++); 
    method(i); 
  }
  public static void main(String[] args) { 
   method(1); 
  } 
}
​

operation result

 

Explanations and justifications

Press-Stack Frame (stack frame) Stack Space method used to make recursive calls. So when a recursive call is too deep, it is possible to run out of Stack Space, broke StackOverflow error.

-Xss128k:设置每个线程的堆栈大小。JDK 5以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。根据应用的线 程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有 限制的,不能无限生成,经验值在3000~5000左右。 ​

线程栈的大小是个双刃剑,如果设置过小,可能会出现栈溢出,特别是在该线程内有递归、大的循环时出现溢出的可能性更 大,如果该值设置过大,就有影响到创建栈的数量,如果是多线程的应用,就会出现内存溢出的错误。


When I let go of what I am , I become what I might be.
走出舒适圈,遇见更好的自己。

发布了91 篇原创文章 · 获赞 63 · 访问量 18万+

Guess you like

Origin blog.csdn.net/qq_38423105/article/details/104731041