JVM

作者: 蓝色猫猫 | 来源:发表于2022-07-13 19:03 被阅读0次

    内存区域

    程序计数器、虚拟机栈、本地方法栈这三个是线程私有的;堆、方法区是线程公有的;

    程序计数器:记录线程走到字节码的哪一行;

    虚拟机栈:由栈帧组成,每个栈帧包含局部变量表、操作数栈、动态链接、方法返回地址,当执行到一个方法的时候,就会把这个方法以栈帧形式压入栈

    本地方法栈:与虚拟机栈差不多,只不过这个栈是给本地方法用的

    堆:堆的垃圾回收算法常用的是分代回收法,所以堆被划分出新生代,老年代;

    方法区: 1.7之前方法区的实现是永久代,会存储已被虚拟机加载的 类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据。****1.8之后方法区的实现变成了元空间,字符串常量池和静态变量等移出到堆内存中,其余的(主要是类型信息)被移到了元空间中。

    元空间和永久代的区别就在于永久代会受JVM的总空间大小的限制,而元空间受限制的是内存的总大小。

    常量池:常量池中主要存放两类数据,一是字面量、二是符号引用。

    字面量:比如String类型的字符串值或者定义为final类型的常量的值。
    符号引用:
    1.类或接口的全限定名(包括他的父类和所实现的接口)
    2.变量或方法的名称
    3.变量或方法的描述信息
    4.this

    当类的字节码被加载到内存中后,他的常量池信息就会集中放入到一块内存,这块内存就称为运行时常量池,并且把里面的符号地址变为真实地址。

    垃圾回收

    判断对象是否能够回收有两个办法:引用计数法可达性分析

    垃圾收集的算法:标记-清除、标记-整理、标记-复制、分代回收法

    分代回收法

    在内存中,分为新生代,老年代,永久代;这里的永久代也有叫方法区。新生代又分为Eden区,S0区,和S1区。一个对象创建,存储在Eden区,当Eden区满了,就会触发Minor GC,存活的对象将进入S0区,S0区满了之后会触发Minor GC,清空S0区内存,将存活的对象复制到S1区;S1满了也是GC清空到S0。倒来倒去,当次数达到16(可改)次时,会进入老年代;老年代满了会触发Full GC(会stop the world)。再满就会OOM了。

    Full GC用的一般是标记整理和标记清除算法,所以不会转移,而Minor GC一般用的是标记-复制算法,所以会转移来转移去,同理,如果对象太大,会直接进老年代。

    类加载过程

    • 加载:
    1. 通过全类名获取定义此类的二进制字节流
    2. 将字节流所代表的静态存储结构转换为方法区的运行时数据结构
    3. 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口
    • 验证:

    验证文件格式、元数据、符号引用、字节码

    • 准备:

    准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,会给类变量一个默认值,不对成员变量做内存分配。

    从概念上讲,类变量所使用的内存都应当在方法区中进行分配。不过有一点需要注意的是:JDK 7 之前,HotSpot 使用永久代来实现方法区的时候,实现是完全符合这种逻辑概念的。 而在 JDK 7 及之后,HotSpot 已经把原本放在永久代的字符串常量池、静态变量等移动到堆中,这个时候类变量则会随着 Class 对象一起存放在 Java 堆中。

    • 解析:

    解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,也就是得到类或者字段、方法在内存中的指针或者偏移量。

    • 初始化:
    1. 给静态变量赋值,给成员变量分配内存,赋值

    类加载器

    JVM 中内置了三个重要的 ClassLoader,除了 BootstrapClassLoader 其他类加载器均由 Java 实现且全部继承自java.lang.ClassLoader

    1. BootstrapClassLoader(启动类加载器) :最顶层的加载类,由 C++实现,负责加载 %JAVA_HOME%/lib目录下的 jar 包和类或者被 -Xbootclasspath参数指定的路径中的所有类。
    2. ExtensionClassLoader(扩展类加载器) :主要负责加载 %JRE_HOME%/lib/ext 目录下的 jar 包和类,或被 java.ext.dirs 系统变量所指定的路径下的 jar 包。
    3. AppClassLoader(应用程序类加载器) :面向我们用户的加载器,负责加载当前应用 classpath 下的所有 jar 包和类。

    双亲委派机制: 自底向上检查类是否被上层加载器加载,再从最顶向下尝试加载类

    双亲委派机制的好处:

    1. 避免类的重复加载
    2. 保护Java核心API不被篡改

    相关文章

      网友评论

          本文标题:JVM

          本文链接:https://www.haomeiwen.com/subject/flytirtx.html