java runtime data area

 

JAVA runtime data area

1. Program Counter

    The Program Counter Register is a small memory space that can be seen as a line number indicator of the bytecode executed by the current thread. In the conceptual model of the virtual machine, when the bytecode interpreter works, it selects the next bytecode instruction to execute by changing the value of this counter.

    Each thread has an independent program counter. This type of memory is also known as "thread private memory".

    If executing a java method, this counter records the address of the virtual machine bytecode instruction being executed. If it is a native method, the counter is empty. This memory area is the only one that does not specify any OutOfMemoryError condition in the Java Virtual Machine Specification.

2.java virtual machine stack

    It is also thread-private and describes the memory model of Java method execution: each method creates a stack frame (Stack Frame) to store information such as local variable table, operand stack, dynamic link, method exit and so on. A method corresponds to a stack frame.

    The local variable table stores various primitive types, object references, and returnAddress types (pointing to the address of a bytecode instruction). Among them, 64-bit long and double occupy two local variable spaces, and the others only occupy one.

    There are two specified exceptions: 1. The depth of the stack requested by the thread is greater than the depth allowed by the virtual machine, and a StackOverflowError exception will be thrown; 2. If the virtual machine can be dynamically expanded, if it cannot apply for enough memory during expansion, it will be Throws OutOfMemoryError exception.

3. Native method stack

    Similar to the Java virtual machine stack, the difference is that the native method stack serves Native methods. Also throws StackOverflowError and OutOfMemoryError.

4. java heap

    The heap is the largest piece of memory managed by the Java Virtual Machine. Shared by all threads, created when the virtual machine starts. The only purpose of the heap area is to store object instances.

The heap can be subdivided into the new generation and the old generation, and the new generation can be subdivided into Eden space, From Survivor space, and To Survivor space.

When the heap cannot be expanded, an OutOfMemoryError exception is thrown.

    Let's take the heap memory of hotspot as an example:

    The heap size can be specified by -Xms, -Xmx.

    The heap is mainly divided into two areas: the new generation (mainly used to store new objects) and the old generation (mainly used to store long-lived objects). The ratio of the young generation to the old generation is 1:2, which can be specified by -XX:NewRatio.

    The new generation is divided into three areas: Eden, From Survivor, To Survivor. The ratio of the three areas is 8:1:1, and the JVM will only use Eden and a Survivor to store objects each time.

    The heap in Java is also the main area where the GC collects garbage. GC is divided into two types: Minor GC, Full GC (or called Major GC). 
    Minor GC is a garbage collection action that occurs in the new generation, and uses a replication algorithm.

    When the object is born in Eden (including a Survivor area, which is assumed to be the from area), after a Minor GC, if the object is still alive and can be accommodated by another Survivor area (the above has been assumed to be the from area, here it should be For the to area, that is, the to area has enough memory space to store the surviving objects in the Eden and from areas), then use the copy algorithm to copy these still surviving objects to another Survivor area (ie the to area), and then clean up The used Eden and Survivor areas (that is, the from area), and the age of these objects is set to 1. In the future, every time the object survives a Minor GC in the Survivor area, the age of the object will be + 1. When the age of the object reaches a certain age When a value (default is 15 years old, can be set by parameter -XX:MaxTenuringThreshold), these objects will become old age. 
    But this is not necessarily the case. For some larger objects (that is, a larger contiguous memory space needs to be allocated), it is directly entered into the old age. The virtual machine provides a -XX:PretenureSizeThreshold parameter, so that objects larger than this setting value are directly allocated in the old age. The purpose of this is to avoid a large number of memory copies between the Eden area and the two Survivor areas (the new generation uses a copy algorithm to collect memory). 
    In order to better adapt to the memory conditions of different programs, the virtual machine does not always require that the age of the object must reach the MaxTenuringThreshold to be promoted to the old age. If the sum of the sizes of all objects of the same age in the Survivor space is greater than half of the Survivor space, Objects with an age greater than or equal to this age can enter the old age directly without waiting for the age required in MaxTenuringThreshold.     Full GC is a garbage collection action that occurs in the old generation, using the "mark-sweep" or "mark-clean" algorithm. 
    现实的生活中,老年代的人通常会比新生代的人 “早死”。堆内存中的老年代(Old)不同于这个,老年代里面的对象几乎个个都是在 Survivor 区域中熬过来的,它们是不会那么容易就 “死掉” 了的。因此,Full GC 发生的次数不会有 Minor GC 那么频繁,并且做一次 Full GC 要比进行一次 Minor GC 的时间更长。 
    在发生MinorGC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么MinorGC可以确保是安全的。如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试这进行一次MinorGC,尽管这次MinorGC是有风险的;如果小于,或者HandlePromptionFailure设置不允许冒险,那这是也要改为进行一次FullGC. 
    另外,标记-清除算法收集垃圾的时候会产生许多的内存碎片 ( 即不连续的内存空间 ),此后需要为较大的对象分配内存空间时,若无法找到足够的连续的内存空间,就会提前触发一次 GC 的收集动作。

        堆设置 
    -Xms :初始堆大小 
    -Xmx :最大堆大小 
    -Xmn:新生代大小。通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90% 
    -XX:NewSize=n :设置年轻代大小 
    -XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4 
    -XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 
    -XX:PermSize=n 永久代(方法区)的初始大小 
    -XX:MaxPermSize=n :设置永久代大小 
    -Xss 设定栈容量;对于HotSpot来说,虽然-Xoss参数(设置本地方法栈大小)存在,但实际上是无效的,因为在HotSpot中并不区分虚拟机和本地方法栈。 
    -XX:PretenureSizeThreshold (该设置只对Serial和ParNew收集器生效) 可以设置进入老生代的大小限制 
    -XX:MaxTenuringThreshold=1(默认15)垃圾最大年龄 如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代. 对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活 时间,增加在年轻代即被回收的概率,该参数只有在串行GC时才有效

5.方法区

    所有线程共享,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

当方法区无法满足内存分配需求时,抛出OutOfMemoryError。

    永久代的垃圾收集主要回收两部分内容:废弃的常量和无用的类。

    废弃的常量:回收废弃常量与回收java堆中的对象非常类似。以常量池字面量的回收为例,加入一个字符串“abc”已经进入了常量池中,但是当前系统没有任何一个String对象是叫做”abc”的,换句话说,就是有任何String对象应用常量池中的”abc”常量,也没有其他地方引用了这个字面量,如果这时发生内存回收,而且必要的话,这个“abc”常量就会被系统清理出常量池。常量池中的其他类(接口)、方法、字段的符号引用也与此类似。(注:jdk1.7及其之后的版本已经将字符串常量池从永久代中移出) 
    无用的类:类需要同时满足下面3个条件才能算是“无用的类”:

  • 该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
  • 加载该类的ClassLoader已经被回收
  • 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

    虚拟机可以对满足上述3个条件的无用类进行回收,这里说的仅仅是”可以“,而并不和对象一样,不使用了就必然会回收。是否对类进行回收,HotSpot虚拟机提供了-Xnoclassgc(关闭CLASS的垃圾回收功能,就是虚拟机加载的类,即便是不使用,没有实例也不会回收。)参数进行控制。

6.运行时常量池

    是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项是常量池(Const Pool Table),用于存放编译期生成的各种字面量和符号引用。并非预置入Class文件中常量池的内容才进入方法运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的intern()方法。

    当方法区无法满足内存分配需求时,抛出OutOfMemoryError。

7.直接内存
    并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。

    JDK1.4加入了NIO,引入一种基于通道与缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。因为避免了在Java堆和Native堆中来回复制数据,提高了性能。

    当各个内存区域总和大于物理内存限制,抛出OutOfMemoryError异常。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326228401&siteId=291194637