JVM-整体结构原理深度解析

JVM定义

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用 Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

2 Java跨平台与JVM的联系
JVM是一个软件,在不同的平台上,JVM有不同的版本。
Java在编译之后会生成一种.class文件,这种文件称为字节码文件。
JVM虚拟机就是将Java编译后的.class文件翻译成特定平台下的机器码,然后运行。也就是说,在不同平台上装上平台对应的JVM虚拟机后,就可以将Java字节码文件转换,然后运行我们的Java程序。
值得注意的是,Java编译后的结果是生成字节码,而不是机器码。字节码是不可以直接运行的,必须通过JVM再次翻译成机器码才可以运行。即使是将Java程序打包成可执行文件,也仍然需要JVM的支持才可以运行。 跨平台的是Java程序,而不是JVM。
JVM是用C/C++开发的,不能平台,不同的平台下JVM的版本是不同的。
(备注: 机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据。)

JVM体系结构概述


JVM启动后,对操作系统来说,JVM是一个的进程,这个进程基本结构包括内容如下

类装载器(ClassLoader)

负责加载class文件,class文件在文件开头有特定的文件标示,并且ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定

执行引擎(Execution Engine)

执行引擎负责解释命令,提交操作系统执行。

本地接口(Native Interface)

Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。 主要是调用c或c++实现的本地接口

本地接口的作用是融合不同的编程语言为Java所用,它的初衷是融合 C/C++程序,Java诞生的时候是C/C++横行的时候,要想立足,必须有调用C/C++程序,于是就在内存中专门开辟了一块区域处理标记为Native的代码,它的具体做法是Native Method Stack中登记Native方法,在Execution Engine 执行时加载Native libraries。

目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过Java程序驱动打印机或者Java系统管理生产设备,在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用Socket通信,也可以使用WebService等等,不多做介绍。

运行时数据区(Runtime Data Area)

执行引擎执行过程中产生的数据会存储在一块内存区域。这块内存区域就是运行时数据区。

JVM内存区域


从图中可以看出jvm的内存区域可以按照 线程共享【堆、方法区】和 线程私有【虚拟机栈、本地方法栈、程序计数器】进行划分。
下面示例 -》对应的原理结构图

线程私有

Java虚拟机栈

描述:

  • 线程执行了一个方法,就会对这个方法调用创建对应的一个栈帧
  • 栈帧中存储了 方法的局部变量表、操作数栈、动态链接、方法出口(方法的返回地址)等信息。
    • 局部变量表
      • 用于存储方法参数和方法内部定义的局部变量。
    • 操作数栈
      • 可以理解为PC寄存器:用于作为计算过程的临时数据存储区。
        • 临时数据指的变量对应的具体值 eg:int a=1; 对应的是1这个值
      • CPU执行load命令时能将数据加载到操作数栈。
    • 动态链接:是在程序运行期间完成的将符号引用替换为直接引用
    • 方法返回地址
      • 方法退出之后都需要返回方法被调用的位置。
        特点:
  • 栈的生命周期(线程生命周期一致)
  • 不存在垃圾回收的问题
  • 可能的异常信息( java.lang.StackOverflowError)

本地方法栈

跟Java虚拟机栈类似的,也是存放各种native方法的局部变量表之类的信息。

程序计数器

描述:

  • 每个线程都有一个程序计数器
  • 用来记录当前执行的字节码指令的位置的(行到了哪一条字节码指令)

线程共享

方法区 -》永久代(Meta Space) | 元数据空间

描述:

  • JVM规范层面的东西
  • jdk1.7 叫做方法区(永久带permGenspace) ;JDK 1.8 + 叫做 方法区( "Metaspace"(元数据空间))
  • 永久带或metaspace是对方法区的不同实现,是实现层面的东西。
    功能:
  • 存储被jvm加载的类的结构信息、常量、静态变量、编译器编译后的代码等
  • 类结构信息:类的名称、方法、字段等信息。
    class文件会被Java虚拟机加载到哪个位置存储-chatgpt
    在传统的Java虚拟机中,.class文件在加载时会被存储在永久代(Permanent Generation)中。永久代是Java虚拟机的一部分,用于存储类的元数据信息,包括类的结构、方法、字段等信息。这意味着在传统的Java虚拟机中,加载的类信息(包括字节码)将占用永久代的空间。

然而,从Java 8开始,永久代被移除,取而代之的是元空间(Metaspace)。在元空间中,类的元数据信息将被动态地分配和管理内存,而不再受到永久代的限制。因此,.class文件的内容会被加载到元空间中。

总体而言,具体的存储位置取决于Java虚拟机的实现版本,而在现代的Java虚拟机中,元空间是类元数据信息的存储区域。

Java堆

描述:
Java进程启动时内存分配: 当通过Java命令启动Java进程时,Java虚拟机会分配一块内存,这块内存包括了不同的区域,如堆空间、方法区(在Java 8之前,现在是元空间)、虚拟机栈、本地方法栈等。
内存的一部分用于创建堆空间,当程序中创建对象的时候,就从堆空间中分配内存。 (扩展:GC 是 JVM 内部的一个进 程,回收无效对象的内存用于将来的分配 )
存储 实例对象(所有的实例对象以及数组都要在堆上进行分配),
Java堆是垃圾收集器管理的主要区域因此很多时候也被称为 "GC堆"。
示例:
可以认为局部变量表里的"replicaManager"指向了Java堆内存里的ReplicaManager对象

4.3 完整流程

JVM内存参数设置

Spring Boot程序的JVM参数设置格式(Tomcat启动直接加在bin目录下catalina.sh文件里):
java ‐Xms2048M ‐Xmx2048M ‐Xmn1024M ‐Xss512K ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐jar microservice‐eurek a‐server.jar
关于元空间的JVM参数有两个:

  • -XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N
  • -XX:MaxMetaspaceSize: 设置元空间最大值, 默认是-1, 即不限制, 或者说只受限于本地内存大小。
  • -XX:MetaspaceSize: 指定元空间触发Fullgc的初始阈值(元空间无固定初始大小), 以字节为单位,默认是21M,达到该值就会触发 full gc进行类型卸载, 同时收集器会对该值进行调整:(动态调整)
    • 如果释放了大量的空间, 就适当降低该值; 如果释放了很少的空间, 那么在不超 过-XX:MaxMetaspaceSize(如果设置了的话) 的情况下, 适当提高该值。这个跟早期jdk版本的-XX:PermSize参数意思不一样,- XX:PermSize代表永久代的初始容量。
  • 由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生 了大小调整,基于这种情况,
  • 一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大, 对于8G物理内存的机器来说,一般我会将这两个值都设置为256M。
相关推荐
Themberfue几秒前
基础算法之双指针--Java实现(下)--LeetCode题解:有效三角形的个数-查找总价格为目标值的两个商品-三数之和-四数之和
java·开发语言·学习·算法·leetcode·双指针
深山夕照深秋雨mo9 分钟前
在Java中操作Redis
java·开发语言·redis
努力的布布14 分钟前
SpringMVC源码-AbstractHandlerMethodMapping处理器映射器将@Controller修饰类方法存储到处理器映射器
java·后端·spring
xujinwei_gingko15 分钟前
Spring MVC 常用注解
java·spring·mvc
PacosonSWJTU19 分钟前
spring揭秘25-springmvc03-其他组件(文件上传+拦截器+处理器适配器+异常统一处理)
java·后端·springmvc
PacosonSWJTU21 分钟前
spring揭秘26-springmvc06-springmvc注解驱动的web应用
java·spring·springmvc
原野心存1 小时前
java基础进阶——继承、多态、异常捕获(2)
java·java基础知识·java代码审计
进阶的架构师1 小时前
互联网Java工程师面试题及答案整理(2024年最新版)
java·开发语言
黄俊懿1 小时前
【深入理解SpringCloud微服务】手写实现各种限流算法——固定时间窗、滑动时间窗、令牌桶算法、漏桶算法
java·后端·算法·spring cloud·微服务·架构
木子02041 小时前
java高并发场景RabbitMQ的使用
java·开发语言