简单了解 JVM

news2024/11/15 21:27:40

 

目录

 

♫什么是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 就是基于分代回收算法回收垃圾的。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络安全培训班有用吗

在当今数字化时代,网络安全问题日益凸显,成为了全球关注的焦点。随着网络攻击的不断升级和复杂化,越来越多的人开始关注网络安全,并考虑参加网络安全培训班来提升自己的技能。那么,网络安全培训班到底有用吗? 一、网络…

如何彻底清除电脑上的数据?保护你的隐私安全

随着科技的飞速发展,电脑已经成为我们日常生活和工作中不可或缺的工具。然而,当我们需要更换电脑、出售旧电脑或处理废旧电脑时,如何彻底清除电脑上的数据成为了一个重要的问题。本文将详细介绍几种彻底清除电脑数据的方法,以确保…

无人机应用新纪元:图形工作站配置推荐与硬件解析

低空经济作为国家新兴的战略性产业,正逐步成为经济高质量发展的新动力。据统计,2023年中国低空经济规模达到5059.5亿元,增速为33.8%,预计到2026年有望突破万亿元大关。政府对低空经济的发展高度重视,不仅出台了相关法规…

IPv6路由基础

RIPng RIPng是一种较为简单的内部网关协议,是RIP在IPv6网络中的应用。RIPng主要用于规模较小的网络中,比如校园网以及结构较简单的地区性网络。由于RIPng的实现较为简单,在配置和维护管理方面也远比OSPFv3和IS-IS for IPv6容易,因…

腾讯地图SDK Android版开发 11 覆盖物示例 4 线

腾讯地图SDK Android版开发 11 覆盖物示例 4 线 前言线的属性介绍ColorType 和 LineTypeColorTypeLineType 与颜色有关的属性填充色和线宽描边颜色和描边的宽度分段颜色渐变色擦除颜色 与纹理相关属性内置纹理自定义颜色纹理线上叠加纹理 虚线 界面布局MapPolyline类常量成员变…

【系统架构设计】基于中间件的开发

【系统架构设计】基于中间件的开发 中间件技术J2EE.NET企业应用集成中间件技术 中间件属于可复用软件的范畴,处于操作系统、网络和数据库之上,应用软件的下层。 J2EE J2EE 是针对 Web Service、业务对象、数据访问和消息报传送的一组规范。这组应用编程接口确定了 Web 应用…

民间故事推广系统小程序的设计

管理员账户功能包括:系统首页,个人中心,用户管理,民族文化管理,节日类型管理,传统节日管理,故事类型管理,民间故事管理,系统管理 微信端账号功能包括:系统首…

基于SpringBoot+Vue+MySQL的IT技术交流和分享平台

系统展示 用户前台界面 管理员后台界面 系统背景 在数字化转型的浪潮中,构建一个基于SpringBoot、Vue.js与MySQL的IT技术交流与分享平台显得尤为重要。该平台旨在汇聚广大IT从业者、开发者及爱好者,提供一个高效、便捷的线上空间,用于分享最新…

7.类的大小

对于C的类而言,类的大小似乎并非完全由用户控制,我们看看如下的代码。 class X {}; class Y : public virtual X{}; class Z : public virtual X{}; class A : public Y, public Z{}; 上述的X,Y,Z,A中没有任何一个class内含有明显的数据,其…

基本开关稳压器(升压结构+降压结构+逆变结构)

2024-9-14,星期六,7:25,天气:多云,心情:晴。明天就就要迎来三天小长假啦,提前祝大家假期快乐,中秋快乐,幸福美满! 今天继续第11章的学习,主要学习…

FOTA介绍

0 Preface / Foreword 1 FOTA 1.1 FOTA介绍 FOTA:Firmware Over-the-Air (FOTA) 1.2 如何产生FOTA文件 (generate FOTA package) 第一步:打开FOTA package tool 第二步:选择flash download配置文件 文件名:flash_download.cf…

Python 常用模块(一):csv模块

目录 一、csv文件介绍二、csv模块2.1 csv模块介绍2.2 csv 模块的基本功能2.3 reader()方法——读取csv文件2.4 writer()方法——将数据写入csv文件2.5 DictWriter类——创建支持字典的csv文件2.6 DictReader类——创建字典类型的csv文件对象2.7 几个常用属性说明2.7.1 QUOTE_AL…

可怕,就算不点,也能中招!macOS神秘的零点击日历漏洞

你有没有想过,连点击都不需要,你的电脑就可能中招?最近的一个macOS漏洞——“零点击日历邀请漏洞”正是这样,它让人有点毛骨悚然。想象一下,你平时收到的那些日历邀请,可能一不留神就让你的系统陷入危机。而更恐怖的是,你根本不需要做任何操作,攻击就会在你眼皮底下悄无…

开发一款应用程序后要做的四件事

首先恭喜您开发了您的移动应用程序!然而创建高质量的应用程序只是迈向成功的第一步。在当今竞争激烈的市场中,让用户发现您的应用至关重要。这就是应用商店优化 (ASO) 发挥作用的地方。 ASO 是优化应用在 Apple App Store 和 Goog…

ROS2 自定义消息 (ACT模型训练参数化为例)

0. 背景 Ubuntu20.04ROS2 foxyPython3.8 (Anaconda) 项目需要,要将ACT模型训练参数化(GitHub - tonyzhaozh/act)。 Qt UI ROS节点(C):从json配置文件读取训练参数,自定义…

LEAN 赋型唯一性(Unique Typing)之 证明过程简介

LEAN论文在证明赋型唯一性(Unique Typing )时,引入了 n-provability 的概念,通过证明在 n-provability 情况下的赋型唯一性,来证明系统的 赋型唯一性。同时,在证明在 n-provability 情况下的赋型唯一性时&a…

Kubernetes实战——基于Helm安装Redis主从模式

目录 一、Helm介绍 1、三大概念 2、基本命令 二、NFS的安装和使用 1、安装NFS 2、NFS在K8s上使用 三、PV和PVC 1、定义 2、PV和PVC的生命周期 2.1、资源供应 2.2、资源绑定 2.3、资源使用 2.4、资源回收 3、创建PV 4、创建PVC 5、创建测试使用PVC的Pod 四、Stor…

基于Qt的串口调试工具

1.项目地址 https://github.com/zhangjiechina001/SerialPortTool 2.核心类 头文件 #ifndef SERIALPORTWRAP_H #define SERIALPORTWRAP_H #pragma execution_character_set("utf-8") #include <QObject> #include <QSerialPort>class SerialPortWrap :…

TDSQL数据库介绍

TDSQL是什么 TDSQL是腾讯云自研企业级分布式数据库&#xff0c;旗下涵盖金融级分布式、云原生、分析型等多引擎融合的完整数据库产品体系&#xff0c;提供业界领先的金融级高可用、计算存储分离、数据仓库、企业级安全等能力&#xff0c;同时具备智能运维平台、Serverless版本…

70、Python之函数式编程:一文搞懂函数式编程的核心概念

引言 从这篇文章开始&#xff0c;我打算稍微聊一下函数式编程&#xff0c;以及Python中对函数式编程有哪些支持&#xff0c;我们在Python中如何应用函数式编程。虽然不会对函数式编程做一个很详尽的讲述&#xff0c;但也会做一个简短的系列性讲述&#xff0c;以便于Python爱好…