JVM架构总结

  • Java虚拟机是用于执行Java文件的程序,是Java语言能够实现优越跨平台性的基础。

JVM总体架构

JVM逻辑结构分区

  • 类装载子系统
  • 字节码执行引擎
  • 运行时数据区:堆、栈、方法区、本地方法栈、程序计数器
    在这里插入图片描述
类加载子系统

类装载器的概述

  • 负责加载class文件,Class文件在文件开头有特定的文件标示,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构并且ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定
字节码执行引擎
  • 负责执行java文件的
运行时数据区
堆:
  • 用于存放对象本身、全局变量
  • features:
    a.它是线程共享的,堆中对象都需要考虑线程安全的问题
    b.有垃圾回收机制,是垃圾收集器管理的主要区域,即GC堆

关于对内存的内部结构:
堆被划分为新生代和老年代,新生代又被进一步划分为Eden和Survivor(幸存者)区
在这里插入图片描述

JVM为每个线程分配固定的堆空间后,一般年轻代占1/3(其中Eden8/10,survivor0(From)占1/10,survivor1(To)占1/10),老年代占2/3。(Java自带的命令行工具,可视化内存的变化情况,jvisualvm)

在堆内存使用的过程中:

  • 当Eden区满后,触发minor GC,回收无效的、无引用的对象;
  • 此后,Eden或survivor0(From)区满,触发minor GC回收Eden和survivor0中的垃圾后,将存活 的对象放到survivor1(To)区;
  • 此后,survivor1区满触发minor GC,回收后存入survivor0区;
  • 继续存活的对象,在survivor0和survivor1区之间来回传递;每传递一次,对象的年龄+1,当年龄>=15,则存入老年代中
  • 老年代:
    ①. Eden 和survivor的比例是8:1,年轻代中的对象基本都是朝生夕死(80%以上),老年代比年轻代内存大。如果老年代内存满了,就会触发majorGC 或者 full GC
    ②. full GC 就会出现所谓的STW(stop the world)现象,即所有的进程都挂起等待清理垃圾
    ③. major GC 是回收老年代的垃圾;Full GC是回收老年代和年轻代的垃圾
  • 每创建一个线程就会创建一个Java栈,每一个Java栈中都会有很多栈帧

  • 栈帧:每个方法运行时需要的内存,有以下一些参数:局部变量表、操作数栈、动态链接、方法出口等,涉及到方法,操作数等的压栈、弹栈的操作。在这里插入图片描述

  • 符合栈的数据结构特征,先进后出,在栈的底部是程序的入口main的栈帧

程序计数器

①. 作用,是记住下一条jvm指令的执行地址

②. 特点:(1)是线程私有的 (2).不会存在内存溢出

③. 注意:在物理上实现程序计数器是在寄存器实现的,整个cpu中最快的一个执行单元

本地方法栈
  • 由于在Java设计之初,C和C++的流行,很多底层的方法也是用它们来实现的,于是专门开辟了一块区域处理标记为native的代码,在字节码执行引擎执行时加载native libraries;
  • 是为虚拟机用到的native方法服务的;
方法区

①. 所有Java虚拟机线程共享的区域,存储了类结构相关的信息 [ 成员变量、方法、构造器 ]等

②. 方法区的创建是在Java 虚拟机启动时被创建,大小不再改变

③. 方法区时逻辑上是堆的一个组成部分,但是在不同虚拟机里头实现是不一样的,最典型的就是永久代(PermGen space)和元空间(Metaspace)
注意:方法区时一种规范,而永久代和元空间是它的一种实现方式

  • 常量池和运行时常量池
    ①. 常量池,就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
    ②. 运行时常量池,常量池是 *.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址
发布了3 篇原创文章 · 获赞 0 · 访问量 27

猜你喜欢

转载自blog.csdn.net/qq_36660190/article/details/104303514