深入理解jvm虚拟机(面试复习)

深入理解jvm虚拟机(面试复习),第1张

深入理解jvm虚拟机(面试复习)

java运行时数据区
类的加载过程
双亲委派机制
程序计数器
虚拟机栈
栈帧结构






红色区域:线程共享
灰色区域:线程私有



类的加载过程

  • 加载: 就是将我们编译后的.class文件从磁盘加载到内存。更准确的说是应该加载到我们的方法区当中。jdk7之前方法区的实现是永久代,jdk7之后方法区叫元空间。
    加载通过类加载器来完成,类加载器有两种,引导类(启动类)加载器(C/C++语言实现),自定义类加载器。将所有派生于ClassLoader的类加载器都划分为自定义类加载器,而引导类加载器(Bootstrap ClassLoader)并没有继承ClassLoader类,用来加载Java核心库中的信息,同时自定义加载器也是有引导类加载器加载。自定义类加载器又分为:Extension Class Loader(扩展类加载器),System Class Loader(AppClassLoader)(系统类加载器),用户自定义加载器。扩展类加载器主要加载ext子目录下的内容。系统类加载器加载程序员自己写的类。其中扩展类加载器为系统类加载器的父加载器,引导类加载器为扩展类加载器的父加载器,这里的父子关系不能理解为Java类的父子继承关系,可以理解为上下级的关系。 最终类的加载是通过那种类型的加载器去执行,有jvm通过双亲委派机制来确定。
  • 链接(验证,准备,解析)
    • 验证:保证被加载类的安全性。
    • 准备:
      • 为类变量(static修饰的成员变量)设置初始值,即零值。并且在jdk1.8之后,类变量会随着Class对象一起存放在java堆中。
      • javac会为被final修饰的变量生成ConstantValue属性,在准备阶段虚拟机会根据ConstantValue属性为变量赋值。
      • 不会为实例变量分配初始值,实例变量会随着对象的实例化一起存放到java堆中。
    • 解析:将常量池中的符号引用转换为直接引用
  • 初始化
    就是执行类构造器方法()的过程。此方法不同于类的构造器,构造器是虚拟机视角下的()方法。()方法不是自定义的,是javac编译器为收集所有对类变量赋值 *** 作的方法,也就是说如果当前类中如果没有类变量,也就没有()。若该类具有父类,jvm会保证子类的()执行前,父类的()已经执行完毕。


双亲委派机制

如果一个类加载器收到了类加载的请求,它会将加载类的任务委托给父类加载器,如果父类加载器还存在父类加载器,继续向上层委托,直到启动类加载器。如果在这个过程中发现当前加载器可以执行加载任务,而当前类加载器的父加载器无法执行加载任务,那么就确定了加载任务的执行者。

双亲委派机制优势

  • 避免类的重复加载,确保一个类的全局唯一性。
  • 保护程序安全,防止核心API被随意篡改。(也叫沙箱安全机制)


程序计数器(pc寄存器)
程序计数器:程序计数器记录的是当前线程的当前方法的下一条要执行的JVM指令地址。如果执行的方法为native(本地方法),程序计数器将不指定值。程序计数器又叫pc寄存器,这里的pc寄存器并非是广义上所指的物理寄存器,是对物理pc寄存器的一种抽象模拟。程序计数器是java运行时数据区唯一一个不存在内存溢出的模块。



虚拟机栈
栈管运行,堆管存储。虚拟机栈主管java程序的运行,它保存方法的局部变量,部分结果,并参与方法的调用和返回,生命周期的线程一致。如果方法中的局部变量为引用类型,则存储的是引用类型变量的地址值。每个方法的调用与结束对应着一次入栈与出栈 *** 作。注意:对栈来说,不存在垃圾回收的问题。所以应该尽量避免出现OOM(内存溢出)的情况。



栈帧结构

  • 局部变量表
    局部变量表是一个数组结构,在编译后就已经确定了数组的长度。主要用来存放方法参数以及定义在方法体内的局部变量,并且局部变量表所需要的容量大小是在编译器确定下来的,在运行期不会改变局部变量表的大小。slot(变量槽) 是局部变量表最基本的存储单元。一个32位以内的基本数据类型只占用一个slot,一个引用数据类型也只占用一个slot。64为的基本数据类型(long,double)占用两个slot。要注意静态方法无法使用this关键字,因为静态方法中没有传入this,而非静态方法默认会传入this。同时局部变量必须进行显示赋值,否则编译不通过。局部变量表中的变量也是重要的垃圾回收根节点,只要被局部变量表中直接或间接引用的对象都不会被回收。

    • slot(变量槽) 可以重复利用,如果一个局部变量过了其作用域,那么在其作用域之后声明的新的局部变量就很可能会复用过期局部变量的槽位,从而达到节省资源的目的。
  • *** 作数栈
    *** 作数栈遵循后进先出的模式,又叫表达式栈。 *** 作数栈的深度在编译后就已经确定了。32位的数据类型占用一个栈的深度,64位的类型占两个栈的深度。在方法的执行过程中,根据字节码指令,往栈中写入数据或提取数据。如果被调用的方法带有返回值,其返回值也会被压入当前栈帧的 *** 作数栈中。

    • 栈顶缓存技术: Hotspot虚拟机是基于栈式架构的虚拟机,他的可移植性好,能够更好的实现跨平台。但是相较于基于寄存器式架构的虚拟机,他的指令更多,执行速度慢,因为需要频繁的执行内存的读写 *** 作。栈顶缓存技术为了提高执行引擎的执行效率,将栈顶元素全部缓存在屋里cpu的寄存器中,以降低对内存的读写次数。
  • 帧数据区

    • 动态链接
      指向运行时常量池中的方法引用。(常量池在class文件中,运行时常量池在方法区)
      • 方法调用
        在方法的执行过程中,需要将符号引用转换为调用方法的直接引用。如果符号引用转换为调用方法的直接引用是在编译器确定下来的,这个转换过程就叫静态链接。对应方法的绑定机制为早期绑定。如果实在运行期间确定下来的,那么这个过程就叫动态链接。对应方法的绑定机制叫晚期绑定。
    • 方法返回地址
      存放调用该方法的pc寄存器的值。
    • 附加信息

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5691633.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存