jvm

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来。

JVM运行时数据区

触发MinorGC(Young GC)
虚拟机在进行minorGC之前会判断老年代最大的可用连续空间是否大于新生代的所有对象总空间

1、如果大于的话,直接执行minorGC

2、如果小于,判断是否开启HandlerPromotionFailure,没有开启直接FullGC

3、如果开启了HanlerPromotionFailure, JVM会判断老年代的最大连续内存空间是否大于历次晋升的大小,如果小于直接执行FullGC

4、如果大于的话,执行minorGC

触发FullGC
老年代空间不足
如果创建一个大对象,Eden区域当中放不下这个大对象,会直接保存在老年代当中,如果老年代空间也不足,就会触发Full GC。为了避免这种情况,最好就是不要创建太大的对象。

持久代空间不足
如果有持久代空间的话,系统当中需要加载的类,调用的方法很多,同时持久代当中没有足够的空间,就出触发一次Full GC

YGC出现promotion failure
promotion failure发生在Young GC, 如果Survivor区当中存活对象的年龄达到了设定值,会就将Survivor区当中的对象拷贝到老年代,如果老年代的空间不足,就会发生promotion failure, 接下去就会发生Full GC.

统计YGC发生时晋升到老年代的平均总大小大于老年代的空闲空间
在发生YGC是会判断,是否安全,这里的安全指的是,当前老年代空间可以容纳YGC晋升的对象的平均大小,如果不安全,就不会执行YGC,转而执行Full GC。

显示调用System.gc

类的加载过程

加载

  1. 通过一个类的全限定名获取定义此类的二进制字节流

  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各个数据的访问入口

    加载 .class 文件的方式:从本地系统中直接加载;通过网络获取,Web Applet;从zip压缩包中读取,jar,war;运行时计算生成,动态代理技术;从其他文件生成,jsp应用等。

链接

验证

确保Class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。

主要包括四种验证:文件格式验证,元数据验证,字节码验证,符号引用验证。

准备

为类变量分配内存并且设置该类变量的默认初始值,即零值。

特例:1)final修饰的static:因为final在编译时就会分配了,准备阶段会显式初始化;2)不会为实例变量初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。

解析

将常量池内的符号引用转换为直接引用的过程。

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等。对应常量池中的 CONSTANT_Class、CONSTANT_Fieldref_info、CONSTANT_Methodref_info等。

堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。

在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除。

Minor GC、Major GC、Full GC的区别:

Minor GC:只是新生代的垃圾收集 Young GC

Major GC:只是老年代的垃圾收集 Old GC,目前只有CMS会有单独收集老年代的行为。

Mixed GC:混合收集,收集整个新生代以及部分老年代的垃圾收集,目前只有G1会有这种行为。

Full GC:整堆收集,收集整个Java堆和方法区的垃圾收集。

内存区域

堆是进程中最大的一块内存,主要用于存放新创建的对象;

方法区主要用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;

虚拟机栈:每个Java方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在JVM栈中入栈到出栈的过程

Author: Jiayi Yang
Link: https://jiayiy.github.io/2020/05/26/jvm/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.