当前位置: 首页 > news >正文

简单了解 JVM

 

目录

 

♫什么是JVM

 ♫JVM的运行流程

 ♫JVM运行时数据区

♪虚拟机栈

♪本地方法栈

♪堆

♪程序计数器

♪方法区/元数据区

 

♫类加载的过程

 

♫双亲委派模型

  ♫垃圾回收机制


♫什么是JVM

JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。 虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统(如:JVM、VMwave、Virtual Box)。  JVM 和其他两个虚拟机的区别是: VMwave与VirtualBox是通过软件模拟物理CPU的指令集,物理系统中会有很多的寄存器,而 JVM则是通过软件模拟Java字节码的指令集,JVM中只是主要保留了PC寄存器,其他的寄存器都进行了裁剪。 

 ♫JVM的运行流程

JVM 是 Java 运行的基础,也是实现一次编译到处执行的关键,那么 JVM 是如何执行的呢?

我们知道程序在执行之前先要把java代码转换成字节码(class文件),而 JVM 首先需要把字节码通过类加载器(ClassLoader)把文件加载到内存中的运行时数据区(Runtime Data Area) ,而字节码文件是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine)将字节码翻译成底层系统指令再交由CPU去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能,这就是这4个主要组成部分的职责与功能。

 ♫JVM运行时数据区

从上图我们可以发现运行时数据区划分成5个部分,接下来我们就来看看他的内存布局。

♪虚拟机栈

虚拟机栈是给 Java 代码使用的栈,每个线程都会有一个,虚拟机栈描述的是 Java 方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息:

①. 局部变量表: 存放了编译器可知的各种基本数据类型(8大基本数据类型)、对象引用。局部变量表 所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,在执行期间不会改变局部变量表大小。简单来说就是存放方法参数和局部变量。

②. 操作栈:每个方法会生成一个先进后出的操作栈。

③. 动态链接:指向运行时常量池的方法引用。

④. 方法返回地址:PC 寄存器的地址。

♪本地方法栈

Native Method Stack 中 Native 就表示 JVM 内部 C++ 写的代码,就是给调用 Native 方法( JVM 内部的方法)准备的栈空间。

♪堆

整个 JVM 中最大的区域,所有 new 出来的对象(类的普通成员变量)都是在堆上。

♪程序计数器

程序计数器是一块比较小的内存空间,记录当前线程执行到哪个指令,可以看做是当前线程所执行的字节码的行号指示器。 如果当前线程正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是一个 Native 方法,这个计数器值为空。

♪方法区/元数据区

元数据区是用来存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据的。

注:虚拟机栈、本地方法栈、程序计数器都是线程私有的(一个线程有一个),堆、元数据区是线程公有的(一个进程里的所有线程共用一个)。

 

♫类加载的过程

Java类加载是将 .class 文件中的二进制数据读入到内存中,并对数据进行校验、解析和初始化的过程类加载来说总共分为以下几个步骤:

♩. 加载:把 .class 文件找到,读取文件内容

♩. 连接:

        ①. 验证:根据 JVM 规范,检查 .class 文件是否符合规范

        ②. 准备:给类对象分配内存空间,设置初始值(基本数据类型设为为 0,引用数据类型设为 null

        ③. 解析:将常量池内的符号引用替换为直接引用的过程,也就是初始化常量的过程。(字符串常量有一块内存空间存字符串的实际内容,还有一个引用保存这块空间的起始地址,类加载前字符串常量存储在 .class 文件中(还没有内存地址),此时这个引用记录的是字符串常量在文件中的”偏移量“(符号引用),在类加载后字符串常量才放到内存里(有了内存地址),才会将”偏移量“替换成内存地址(直接引用))

♩. 初始化:

真正对类对象里的内容进行加载,加载父类、执行静态代码块

注:java 程序运行后不会把所有类一次性都加载,而是需要用到哪个再加载哪个

 

♫双亲委派模型

类加载描述的是找到 .class 文件读取内容的过程,而双亲委派模型描述的就是加载、找 .class文件的基本过程。了解双亲委派模型前,我们得先了解下 JVM 默认提供的三种类加载器:♩. BootstrapClassLoader负责加载标准库中的类(java 规范要求提供的类,无论哪种 JVM 都会提供)

♩. ExtensionClassLoader负责加载 JVM 扩展库中的类(规范之外,由 JVM 厂商提供的扩展功能)

♩. ApplicationClassLoader负责加载用户提供的第三方库/用户项目代码中的类 

这三个加载器彼此存在“父子类”的关系, BootstrapClassLoader 相当于 ExtensionClassLoder 的父加载器,ExtensionClassLoder 相当于 ApplicationClassLoder的父加载器。

双亲委派模型就是单加载一个类时,首先从 ApplicationClassLoader 开始,但 ApplicationClassLoader 会把加载任务交给父加载器 ExtensionClassLoader , ExtensionClassLoader 又会把加载任务交给父加载器 BootstrapClassLoader ,BootstrapClassLoader 没有父加载器才开始搜索标准库目录的类,找到了就加载,没找到就交给子加载器 ExtensionClassLoader,ExtensionClassLoader 搜索扩展库的目录,找到了就加载,没找到就交给子加载器 ApplicationClassLoader,ApplicationClassLoader 搜索用户项目相关目录,找到了就加载,没找到就抛出异常。

注:双亲委派模型的加载顺序确保了 BootstrapClassLoader 先加载,ApplicationClassLoader 后加载,可以避免因用户自己写的类导致 JVM 已有代码的混乱。

  ♫垃圾回收机制

垃圾回收机制即 GC 主要是对堆进行释放的,是以对象为单位进行回收的,因此也叫死亡对象的回收。

要想回收垃圾,首先得判断谁是垃圾,常见的判断是否为垃圾的方法有两种:

♩.引用计数

给每个对象都分配一个计数器,有引用指向它,计数器加一;有指向它的引用销毁,计数器减一。

显然这个方法简单有效,但还是存在缺点:内存浪费的多且可能存在循环引用(a 对象的属性指向 b,b 对象的属性指向 a,当 a 和 b 销毁时,a 和 b 的引用计数仍为 1)的问题。

♩.可达性分析

java 里的对象都是通过引用指向来访问的,通过遍历所有对象的引用指向就可以判断出某个对象可达不可达,java 的做法就是通过可达性分析。

确认了哪个对象是垃圾就可以对垃圾进行回收,常见的回收垃圾的做法有:

♩.标记清除

基本概念:标记清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。在标记阶段,它从根节点开始遍历,标记所有可达的对象。未被标记的对象被视为垃圾,这些对象在清除阶段被回收。


优点:标记清除算法实现简单,不需要移动存活对象。
缺点:标记清除算法执行效率较低,且清除后容易产生大量不连续的内存碎片,这可能导致后续对象分配时找不到足够的连续内存空间而提前触发垃圾回收。

♩.复制算法

基本概念:复制算法将内存分为两块,每次只使用其中一块。当一块内存用完时,将还存活的对象复制到另一块上,然后清理掉已使用的内存。

优点:由于只处理其中一块内存区域,复制算法运行速度较快,且不会产生内存碎片。

缺点:复制算法需要两倍的内存空间,代价较高。同时,如果对象的生命周期较长,这种复制操作会导致效率低下。

♩.标记整理

基本概念:标记整理算法结合了标记清除和复制算法的优点。在标记阶段后,将所有存活对象压缩到内存的一端,然后清理边界以外的内存。


优点:标记整理算法避免了标记清除算法的碎片问题,也不需要复制算法那么多的内存空间。
缺点:标记整理算法实现较为复杂,且移动对象的过程会产生额外的开销。

♩.分代回收

基本概念:分代收集算法基于这样一个事实:大部分对象会在年轻时死亡。它将堆内存分为新生代和老年代,不同年代采用不同的回收算法。新 new 出来的对象在伊甸区,熬过一轮 GC 就通过复制算法来到了幸存区,幸存也要经过周期性的 GC 考验,如果通过考验就进入另一个幸存区,没通过就释放掉,当一个对象在两个幸存区来回拷贝很多次了后就进入老年区,老年区偶而也要经历 GC 的考验,如果没通过就通过标记整理算法释放掉。


优点:分代收集算法通过将内存分区,可以更高效地回收垃圾,特别是针对新生代中大量短命的对象。
缺点:分代收集算法设计相对复杂,需要根据不同代的特点选择合适的回收算法。

注:JVM 就是基于分代回收算法回收垃圾的。

相关文章:

简单了解 JVM

目录 ♫什么是JVM ♫JVM的运行流程 ♫JVM运行时数据区 ♪虚拟机栈 ♪本地方法栈 ♪堆 ♪程序计数器 ♪方法区/元数据区 ♫类加载的过程 ♫双亲委派模型 ♫垃圾回收机制 ♫什么是JVM JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。 虚拟机是指通过软件模…...

已经30岁了,想转行从头开始现实吗?什么样的工作算好工作?

我是29岁那年,完成从转行裸辞副业的职业转型。 如果你把职业生涯看成是从现在开始30岁,到你退休那年,中间这么漫长的30年,那么30岁转行完全来得及; 如果你觉得必须在什么年纪,什么时间内必须完成赚到几十…...

快速理解docker(一)docker 简介

在当今快速迭代的软件开发环境中,如何高效地部署、管理和扩展应用程序成为了开发者们面临的重大挑战。Docker,作为一款开源的容器化平台,凭借其轻量级、可移植性和易于部署的特性,迅速成为了解决这些挑战的热门选择。本文将带您走…...

RHCS认证-Linux(RHel9)-Ansible

文章目录 一、ansible 简介二 、ansible部署三、ansible服务端测试四 、ansible 清单inventory五、Ad-hot 点对点模式六、YAML语言模式七、RHCS-Ansible附:安装CentOS-Stream 9系统7.1 ansible 执行过程7.2 安装ansible,ansible-navigator7.2 部署ansibl…...

【Python】Spyder:科学 Python 开发环境

在数据科学和科学计算领域,Python 已经成为了一个不可或缺的工具。为了提高开发效率和改善编程体验,一个功能强大且用户友好的开发环境是必需的。Spyder(Scientific Python Development Environment)正是这样一个为科学计算和数据…...

SpringBootWeb响应

2. 响应 前面我们学习过HTTL协议的交互方式:请求响应模式(有请求就有响应) 那么Controller程序呢,除了接收请求外,还可以进行响应。 2.1 ResponseBody 在我们前面所编写的controller方法中,都已经设置了…...

CMake 构建Qt程序弹出黑色控制台

CMake 构建Qt程序弹出黑色控制台...

虚拟机centos_7 配置教程(镜像源、配置centos、静态ip地址、Finalshell远程操控使用)

文章目录 一、下载镜像源(准备工作)1、开源网站2、下载 二、VMware配置centos三、配置静态IP地址四、Finalshell使用1、下载Finalshell2、连接虚拟机 五、谢谢观看! 一、下载镜像源(准备工作) 1、开源网站 有许多开源…...

git 删除 git push 失败的记录

文章目录 问题分析 问题 git push 失败后如何清理 commit 提交的内容 当我们 git push 失败后,如果下次有新的改动需要push时,会出现如下报错 分析 找到需要回退的那次commit的 哈希值 git log然后就回退到了指定版本,这个时候再把新修改…...

【专题】2024年中国白酒行业数字化转型研究报告合集PDF分享(附原数据表)

原文链接:https://tecdat.cn/?p37755 消费人群趋于年轻化,消费需求迈向健康化,消费场景与渠道走向多元化,这些因素共同驱动企业凭借数据能力来适应市场的变化。从消费市场来看,消费群体、需求、场景及渠道皆展现出与…...

哪款品牌充电宝性价比比较高?五款性价比绝佳充电宝推荐

在现代生活中,充电宝已经成为我们日常出行和工作的必备品。然而,面对市场上琳琅满目的充电宝品牌,大家往往难以抉择。尤其是在近期,充电宝不合格产品的数量持续上升,据最新抽查结果显示,不合格率已经上升到…...

巨坑!!华为大数据平台sparksql,连接gauss200数据库

最近用华为大数据平台fusion6.5平台,写了一个sparksql 读取gauss200的MPP数据库的程序。 首先将spark 相关的jar依赖包,必须在华为大数据平台的客户端的spark/jars 这个文件里面去找到然后添加到idea 依赖里面。打包要把整体包打在里面。 核心代码片段…...

BGP相关知识笔记

技术背景: 在只有IGP(诸如OSPF、IS-IS、RIP等协议,因为最初是被设计在一个单域中进行一个路由操纵,因此被统一称为Interior Gateway Protocol,内部网关协议)的时代,域间路由无法实现一个全局路由…...

在 Windows 上运行 Vue 项目时解决 ‘NODE_OPTIONS‘ 错误

在 Windows 上运行 Vue 项目时解决 ‘NODE_OPTIONS’ 错误 在 Windows 系统上启动 Vue 项目时,遭遇报错。具体报错信息如下: ‘NODE_OPTIONS‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。这个错误通常意味着 Windows 系统无法识…...

面试真题:谈一谈Mysql的分库分表

分表和分库是什么?有什么区别? 分库是一种水平扩展数据库的技术,将数据根据一定规则划分到多个独立的数据库中。每个数据库只负责存储部分数据,实现了数据的拆分和分布式存储。分库主要是为了解决并发连接过多,单机 my…...

玄机靶场--蚁剑流量

木马的连接密码是多少 黑客执行的第一个命令是什么 id 黑客读取了哪个文件的内容,提交文件绝对路径 /etc/passwd 黑客上传了什么文件到服务器,提交文件名 黑客上传的文件内容是什么 黑客下载了哪个文件,提交文件绝对路径 蚁剑流量特征总结 …...

uniapp map设置高度为100%后,会拉伸父容器的高度

推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...

CICD从无到会

一 CICD是什么 CI/CD 是指持续集成(Continuous Integration)和持续部署(Continuous Deployment)或持续交付(Continuous Delivery) 1.1 持续集成(Continuous Integration) 持续集成是…...

责任链模式优化 文章发布的接口(长度验证,敏感词验证,图片验证等环节) 代码,示例

需求:后端需要提供一个文章发布的接口,接口中需要先对文章内容进行如下校验,校验通过后才能发布 1. 文章长度不能超过1万个字符 2. 不能有敏感词 3. 文章中图片需要合规 责任链相当于一个链条一样,链条上有很多节点,节…...

Java流程控制语句——条件控制语句详解(附有流程图)#Java条件控制语句有哪些?#if-else、switch

在 Java 编程中,条件控制语句用于控制程序的执行路径,决定根据某些条件来选择执行某段代码或跳过某段代码。它们是 Java 编程的重要组成部分,帮助开发者根据不同的输入、状态或数据流来编写更加灵活和动态的代码。在本文中,我们将…...

十一、SOA(SOA的具体设计模式)

我们现在深入学习SOA的具体设计模式。SOA架构中的设计模式主要是指导服务如何设计、实现、部署和管理,确保服务的松耦合、高可用性、扩展性和复用性。SOA常见的设计模式可以分为以下几类: 1. 服务层次设计模式 1.1. 基础服务(Fundamental S…...

Mybatis原理

一. 为什么要使用Mybatis? 1.1 jdbc的使用步骤 首先,在pox.xml中引入MySQl驱动的依赖 第一步, Class.forName 注册驱动 第二步,获取一个Connection。 第三步,创建一个Statement对象。 第四步,execute()方法执行SQL。execute()方…...

黑马头条day3-2 自媒体文章管理

前边还有一个 素材列表查询 没什么难度 就略过了 查询所有频道和查询自媒体文章也是和素材列表查询类似 就是普通的查询 所以略过了 文章发布 这个其实挺复杂的 一共三张表 一个文章表 一个素材表 一个文章和素材的关联表 区分修改与新增就是看是否存在id 如果是保存草稿…...

JinDouYun性能测试工具使用方法

1.功能介绍 2. 安卓端支持安卓6及以上的版本,ios支持大部分版本 3. 可以测试游戏,视频,普通应用的性能数据,数据精准,低延迟,无侵入 4.工具下载链接 筋斗云 5.后续功能添加,高版本支持&…...

操作系统 | 学习笔记 | | 王道 | 5.3 磁盘和固态硬盘

5.3 磁盘和固态硬盘 5.3.1 磁盘 磁盘结构 磁盘:磁盘的表面由一些磁性物质组成,可以用这些磁性物质来记录二进制数据 磁道:磁盘的盘面被划分成一个个磁道。这样的一个“圈”就是一个磁道 扇区:一个磁道又被划分成一个个扇区&am…...

【Oauth2整合gateway网关实现微服务单点登录】

文章目录 一.什么是单点登录?二.Oauth2整合网关实现微服务单点登录三.时序图四.代码实现思路1.基于OAuth2独立一个认证中心服务出来2.网关微服务3产品微服务4.订单微服务5.开始测试单点登录 一.什么是单点登录? 单点登录(Single Sign On&…...

WEB领域是不是黄了还是没黄

进入2024年后,WEB领域大批老表失业,一片哀嚎,个个饿的鬼叫狼嚎,为啥呢,下面是我个人的见解和看法。 中国程序员在应用层的集中 市场需求:中国的互联网行业在过去几年中经历了爆炸性增长,尤其是…...

Android系统:系统架构

文章目录 分层设计分块设计总结 分层设计 自上而下分为:应用层、应用架构层、系统运行层、硬件抽象层、Linux内核层 应用层 封装一系列系统App 应用架构层(Framework) 封装一系列运行App需要的Java框架 提供App开发需要的API 系统运行层(Libraries) 封装一系…...

NCNN 源码(1)-模型加载-数据预处理-模型推理

参考 ncnn 第一个版本的代码。 0 整体流程 demo:squeezenet ncnn 自带的一个经典 demo:squeezenet 的代码: // 网络加载 ncnn::Net squeezenet; squeezenet.load_param("squeezenet_v1.1.param"); squeezenet.load_model("squeezenet_…...

重修设计模式-结构型-享元模式

重修设计模式-结构型-享元模式 复用不可变对象,节省内存 享元模式(Flyweight Pattern)核心思想是通过共享对象方式,达到节省内存和提高性能的目的。享元对象需是不可变对象,因为它会被多处代码共享使用,要避…...