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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/518510.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android14 Handle机制

Handle是进程内部, 线程之间的通信机制. handle主要接受子线程发送的数据, 并用此数据配合主线程更新UI handle可以分发Message对象和Runnable对象到主线程中, 每个handle实例, 都会绑定到创建他的线程中, 它有两个作用,: (1) 安排消息在某个主线程中某个地方执行 (2) 安排…

从安卓转战月薪6万的鸿蒙原来这么简单

近年来,各家大厂正在积极布局鸿蒙客户端开发,鸿蒙操作系统备受瞩目,不少安卓开发者纷纷转战鸿蒙,并取得了可观的经济回报。本文将为大家揭示,从安卓转战鸿蒙并获得月薪6万的简单之道,希望能给正在考虑转型的…

【center-loss 中心损失函数】 参数与应用

文章目录 前言简单总结一下参数对比解释参数权重衰减(L2正则化)动量其他参数运行 前言 之前我们已经完全弄明白了中心损失函数里的代码是什么意思,并且怎么用的了,现在我们来运行它。 论文:https://ydwen.github.io/…

基于Springboot免费搭载轻量级阿里云OSS数据存储库(将本地文本、照片、视频、音频等上传云服务保存)

一、注册阿里云账户 打开https://www.aliyun.com/,申请阿里云账户并完成实名认证(个人)。这种情况就是完成了: 二、开通OSS服务 点击立即开通即可。 三、创建Bucket 申请id和secert: 进去创建一个Accesskey就会出现以…

Linux 实现打印彩色进度条

文章目录 预备知识一、理解回车换行二、认识行缓冲1、代码一、二(回车换行理解)2、代码三、四(sleep函数和ffush函数理解) 三、简单倒计时1. 倒计时代码2、效果展示 四、进度条1、效果展示2、进度条代码makefileProcessBar.hProce…

前端如何上传图片给后台?如何传递 multipart/form-data 类型的数据?图片大小、格式检查?

1. 如何上传图片? 图片上传需要传二进制流,请求头的 content-type 类型需为 multipart/form-data,传递的格式如下图所示 前后端交互通常为: 先调用接口上传二进制流图片然后再上传表单其他内容(第一步通常会返回后台…

从 HPC 到 AI:探索文件系统的发展及性能评估

随着 AI 技术的迅速发展,模型规模和复杂度以及待处理数据量都在急剧上升,这些趋势使得高性能计算(HPC)变得越来越必要。HPC 通过集成强大的计算资源,比如 GPU 和 CPU 集群,提供了处理和分析大规模数据所需的…

Canvas笔记04:绘制九大基本图形的方法,重头戏是贝塞尔曲线

hello,我是贝格前端工场,最近在学习canvas,分享一些canvas的一些知识点笔记,本期分享canvas绘制图形的知识,欢迎老铁们一同学习,欢迎关注,如有前端项目可以私信贝格。 Canvas是HTML5中的一个绘…

1分钟帮你快速搞定遥测终端机RTU选型!

遥测终端机RTU-MGTR-W系列 精准应对贴心服务每一个关键场景 MGTR-W系列遥测终端机在水利水务领域有着广泛的应用,能够满足各种细分场景的需求。该系列终端机助力实现灌区信息化、高标准农田建设、农村供水信息化、水库雨水情监测、大坝安全监测、地下水监测以及水…

使用Python来发送电子邮件(手把手教学)

一、首先得准备两个邮箱 1、接收邮箱地址随意(可以再添加一个QQ邮箱做接收用), 2、重点是发送邮箱,发送邮箱这里使用的是QQ邮箱: ① 打开一个web,登录QQ邮箱: 右上角: ②安全设置-…

如何恢复edge的自动翻译功能

介绍:对于英文不好的小伙伴,把英语翻译成中文是有帮助的,而edge可以直接对英文页面翻译这一功能更是受人喜爱,但是,最近发现这一项功能消失了。 原始界面: 下面展示如何恢复该功能。 1.打开edge&#xff…

JavaScript实现遍历精灵图的效果

问题描述&#xff1a;通过JavaScript将精灵图里面的小图标给遍历出来。 关键代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width…