简单了解 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 编程的重要组成部分,帮助开发者根据不同的输入、状态或数据流来编写更加灵活和动态的代码。在本文中,我们将…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...