In-depth understanding of the Java Virtual Machine (JVM)

In-depth understanding of the Java Virtual Machine (JVM)

 

1. JVM memory partition and function

The java virtual machine is mainly divided into the following areas:

Method area:
1. Sometimes it also becomes permanent generation . Garbage collection rarely occurs in this area, but it does not mean that GC does not occur. The GC performed here is mainly to unload the constant pool and type in the method area.
2 . The method area is mainly used to store data such as class information, constants, static variables and code compiled by the just-in-time compiler that have been loaded by the virtual machine.
3. The area is shared by threads.
4. There is a runtime constant pool in the method area, which is used to store literals and symbolic references generated by static compilation. The constant pool is dynamic, which means that constants are not necessarily determined at compile time, and constants generated at runtime will also exist in this constant pool.

Virtual machine stack:
1. The virtual machine stack is what we usually call stack memory . It serves java methods. When each method is executed, a stack frame is created to store the local variable table, operand stack, dynamic Information such as links and method exits.
2. The virtual machine stack is private to the thread, and its life cycle is the same as that of the thread.
3. The basic data type, returnAddress type (pointing to the address of a bytecode instruction) and object reference are stored in the local variable table. This object reference may be a pointer to the starting address of the object, or it may represent the object. The handle or location associated with the object. The memory space required for local variables is determined between compilers
4. The function of the operand stack is mainly used to store the result of the operation and the operand of the operation. It is different from the local variable table, which is accessed by index, but is pushed and popped from the stack. Method
5. Each stack frame contains a reference to the method to which the stack frame belongs in the runtime constant pool. This reference is held to support dynamic connection during method invocation. Dynamic linking is to reference the symbols in the constant pool in the Runtime translates to direct references.

Local method stack
The local method stack is similar to the virtual machine stack, except that the local method stack serves the Native method.

Heap
Java heap is a piece of memory shared by all threads. It is created when the virtual machine starts. Almost all object instances are created here, so garbage collection operations often occur in this area.

The program counter has
a small memory space, and the bytecode interpreter can select the next bytecode instruction to be executed by changing the count value when it is working. Functions such as branching, looping, jumping, exception handling and thread recovery all need to rely on this counter to complete . This memory area is the only one where the Java Virtual Machine specification does not specify any OOM situation.

 

2. The method of determining whether the object is alive or not

There are two ways to judge whether an object is alive:
1.  Reference counting method The
so-called reference counting method is to set a reference counter for each object. Whenever there is a place to refer to the object, the counter is incremented by one. When the reference is invalid, the counter Just subtract one. When the reference counter of an object is zero, it means that the object is not referenced, that is, a "dead object", and will be garbage collected.
A drawback of the reference counting method is that it cannot solve the problem of circular references, that is, when object A references Object B, object B also refers to object A, then the reference counters of objects A and B are not zero at this time, which makes it impossible to complete garbage collection, so mainstream virtual machines do not use this algorithm.

2. Reachability algorithm (reference chain method)
The idea of ​​this algorithm is to start a downward search from an object called GC Roots . If an object does not have any reference chain connected to GC Roots, it means that the object is unavailable. .
Objects that can be used as GC Roots in java are as follows:

  • Objects referenced in the virtual machine stack
  • The object referenced by the static property of the class in the method area
  • The object referenced by the method area constant pool
  • Objects referenced by the native method stack JNI

虽然这些算法可以判定一个对象是否能被回收,但是当满足上述条件时,一个对象比不一定会被回收。当一个对象不可达GC Root时,这个对象并 
不会立马被回收,而是出于一个死缓的阶段,若要被真正的回收需要经历两次标记
如果对象在可达性分析中没有与GC Root的引用链,那么此时就会被第一次标记并且进行一次筛选,筛选的条件是是否有必要执行finalize()方法。当对象没有覆盖finalize()方法或者已被虚拟机调用过,那么就认为是没必要的。
如果该对象有必要执行finalize()方法,那么这个对象将会放在一个称为F-Queue的对队列中,虚拟机会触发一个Finalize()线程去执行,此线程是低优先级的,并且虚拟机不会承诺一直等待它运行完,这是因为如果finalize()执行缓慢或者发生了死锁,那么就会造成F-Queue队列一直等待,造成了内存回收系统的崩溃。GC对处于F-Queue中的对象进行第二次被标记,这时,该对象将被移除”即将回收”集合,等待回收

 

3. Java垃圾回收机制

在java中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

 

4. Java中垃圾收集的方法

  1. 标记-清除:
    这是垃圾收集算法中最基础的,根据名字就可以知道,它的思想就是标记哪些要被回收的对象,然后统一回收。这种方法很简单,但是会有两个主要问题:1.效率不高,标记和清除的效率都很低;2.会产生大量不连续的内存碎片,导致以后程序在分配较大的对象时,由于没有充足的连续内存而提前触发一次GC动作。
  2. 复制算法:
    为了解决效率问题,复制算法将可用内存按容量划分为相等的两部分,然后每次只使用其中的一块,当一块内存用完时,就将还存活的对象复制到第二块内存上,然后一次性清楚完第一块内存,再将第二块上的对象复制到第一块。但是这种方式,内存的代价太高,每次基本上都要浪费一般的内存。
    于是将该算法进行了改进,内存区域不再是按照1:1去划分,而是将内存划分为8:1:1三部分,较大那份内存交Eden区,其余是两块较小的内存区叫Survior区。每次都会优先使用Eden区,若Eden区满,就将对象复制到第二块内存区上,然后清除Eden区,如果此时存活的对象太多,以至于Survivor不够时,会将这些对象通过分配担保机制复制到老年代中。(java堆又分为新生代和老年代)
  3. 标记-整理
    该算法主要是为了解决标记-清除,产生大量内存碎片的问题;当对象存活率较高时,也解决了复制算法的效率问题。它的不同之处就是在清除对象的时候现将可回收对象移动到一端,然后清除掉端边界以外的对象,这样就不会产生内存碎片了。
  4. 分代收集 
    现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代和老年代。在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记-整理 或者 标记-清除

 

5. Java内存分配与回收策略

 5.1对象优先在Eden分配: 
  大多数情况对象在新生代Eden区分配,当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC 
 5.2大对象直接进入老年代: 
  所谓大对象就是指需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串以及数组。这样做的目的是避免Eden区及两个Servivor之间发生大量的内存复制 
 5.3长期存活的对象将进入老年代 
  如果对象在Eden区出生并经历过一次Minor GC后仍然能存活,并且能够被Servivor容纳,将被转移到Servivor空间中,并且把对象年龄设置成为1,如果对象在Servivor区每熬过一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度(默认15岁),就将会被晋级到老年代中 
 5.4动态对象年龄判定 
 为了更好的适应不同程序的内存状况,虚拟机并不是永远要求对象的年龄必须达到了MaxTenuringThreshold才能晋级到老年代,如果在Survivor空间中相同年龄所有对象的大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入到老年代,无须登到MaxTenuringThreshold中要求的年龄。 
 空间分配担保: 
 在发生Minor GC之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果条件成立,那么Minor GC可以确保是安全的,如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许那么会继续检查老年代最大可用的连续空间是否大于晋级到老年代对象的平均大小,如果大于,将尝试进行一次Minor GC,尽管这次Minor GC是有风险的,如果小于,或者HandlePromotionFailure设置不允许冒险,那这时也要改为进行一次Full GC。

 

6. Java类加载机制

虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的java类型。

 

7. Java类加载过程

java类加载需要经历一下7个过程:
加载
加载时类加载的第一个过程,在这个阶段,将完成一下三件事情:
1. 通过一个类的全限定名获取该类的二进制流。
2. 将该二进制流中的静态存储结构转化为方法去运行时数据结构。 
3. 在内存中生成该类的Class对象,作为该类的数据访问入口。

验证
验证的目的是为了确保Class文件的字节流中的信息不回危害到虚拟机.在该阶段主要完成以下四钟验证:
1. 文件格式验证:验证字节流是否符合Class文件的规范,如主次版本号是否在当前虚拟机范围内,常量池中的常量是否有不被支持的类型.
2. 元数据验证:对字节码描述的信息进行语义分析,如这个类是否有父类,是否集成了不被继承的类等。
3. 字节码验证:是整个验证过程中最复杂的一个阶段,通过验证数据流和控制流的分析,确定程序语义是否正确,主要针对方法体的验证。如:方法中的类型转换是否正确,跳转指令是否正确等。
4. 符号引用验证:这个动作在后面的解析过程中发生,主要是为了确保解析动作能正确执行。

准备
准备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行分配。准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配在Java堆中。

public static int value=123;//在准备阶段value初始值为0 。在初始化阶段才会变为123 。

解析
该阶段主要完成符号引用到直接引用的转换动作。解析动作并不一定在初始化动作完成之前,也有可能在初始化之后。

初始化
初始化时类加载的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码。

 

8. 类加载器双亲委派模型机制

当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类去加载,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。

 

9.类加载器分类

实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。

主要有一下四种类加载器:

1. 启动类加载器(Bootstrap ClassLoader)用来加载java核心类库,无法被java程序直接引用。

2. 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。

3. 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。

4. 用户自定义类加载器,通过继承 java.lang.ClassLoader类的方式实现。

 

 

Guess you like

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