JAVA虚拟机----JVM

news2024/11/13 9:08:14

(一)认识JVM

     JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。
    虚拟机是指通过软件模拟的具有完整硬件功能的、运⾏在⼀个完全隔离的环境中的完整计算机系统。
     常⻅的虚拟机:JVM、VMwave、Virtual Box。

(二)JVM运行流程

    程序在执行前要把java代码转为.class文件,JVM首先要将.class文件通过类加载器加载到运行时数据区,但是.class文件不可以直接给底层操作系统执行,需要特定的解析器将字节码翻译成底层系统指令再给CPU去执行,这个过程需要调用其他语言的接口---本地库接口

(三)JVM的内分划分

JVM的内存由五部分组成:

1.堆

   堆用来存储我们new出来的对象,并且堆是所有线程共享的

   堆里面分为两个区域:新生代和老生代,新生代存放新建的对象,当个经过数次GC后还存活的对象会放入老生代,具体我们会在JVM垃圾回收机制中说明  

2.栈

    栈分为两种,一种时虚拟机栈,一种是本地方法栈,栈是线程私有的,每个线程都有自己的虚拟机栈,且生命周期和线程是相同的。

    栈具体描述的是JAVA方法执行的内存模型,每个方法在执行时都会创建一个栈帧,用来存储局部变量等信息

    java虚拟机中的栈叫虚拟机栈,本地方法的栈叫本地方法栈

3.程序计数器

   程序计数器也是线程私有的,用来存放下一条指令的地址,如果当前线程正在执⾏的是⼀个Java⽅法,这个计数器记录的是正在执⾏的虚拟机字节码指令的地址;如果正在执⾏的是⼀个Native⽅法,这个计数器值为空。

4.元数据区(方法区)

用来存储虚拟机加载的类信息,常量和静态变量等数据的

JDK 1.8 元空间的变化
1. 对于 HotSpot 来说,JDK 8 元空间的内存属于本地内存,这样元空间的⼤⼩就不在受 JVM 最内
存的参数影响了,⽽是与本地内存的⼤⼩有关。
2. JDK 8 中将字符串常量池移动到了堆中。运⾏时常量池
运⾏时常量池是⽅法区的⼀部分,存放字⾯量与符号引⽤。
字⾯量 : 字符串(JDK 8 移动到堆中) 、final常量、基本数据类型的值。
符号引⽤ : 类和结构的完全限定名、字段的名称和描述符、⽅法的名称和描述符。

(四)JVM的类加载机制

对于一个类来说,我们需要经过加载->验证->准备->解析->初始化这五个步骤

接下来我们看看具体每个步骤要如何执行内容

1.加载

加载阶段是整个类加载中的一个过程,我们需要在这个阶段完成:

1)通过⼀个类的全限定名来获取定义此类的⼆进制字节流。
2)将这个字节流所代表的静态存储结构转化为⽅法区的运⾏时数据结构。
3)在内存中⽣成⼀个代表这个类的java.lang.Class对象,作为⽅法区这个类的各种数据的访问⼊。

2.验证

   我们加载阶段生成了一个.class文件,我们要确保这个.class文件是正确的,包含的信息符合我们的要求,验证就是为了确保.class文件正确性的,我们需要验证:文件格式,字节码,符号引用等。

3.准备

   准备是为类中定义的2变量分配内存并且设置类变量的初始值的,我们定义了变量在这个阶段,还没有被赋值,只有初始值,我们这时候看,就全为0

4.解析

  解析阶段是 Java 虚拟机将常量池内的符号引⽤替换为直接引⽤的过程,也就是初始化常量的过程

5.初始化

初始化阶段,我们JVM才开始真正执行类中编写的程序代码,将主导权交给程序

双亲委派模型

自从JDK1.2以来,java就一直保持三层类加载器,双亲委派的类加载架构器

    那我们来说一下他的工作过程:如果⼀个类加载器收到了类加载的请求,它⾸先不会⾃⼰去尝试加载这个类,⽽是把这个请求委派给⽗类加载器去完成,每⼀个层次的类加载器都是如此,因此所有的加载请求最 终都应该传送到最顶层的启动类加载器中,只有当⽗加载器反馈⾃⼰⽆ 法完成这个加载请求(它的搜索范围中没有找到所需的类)时,⼦加载器才会尝试⾃⼰去完成加载。

  由上到下我们查找的顺序是:先去标准库下查找,查找不到再去扩展库中查找,如果仍然查不到就会去第三方库或者我们自己写的方法中查找

优点:1.避免类的重复加载,如果a和b都有一个父类c,那么当a启动时就会把c加载起来,那么b类在进行加载时就不需要再重复加载c了

2.安全性:使⽤双亲委派模型也可以保证了 Java 的核⼼ API 不被篡改,如果没有使⽤双亲委派模
型,⽽是每个类加载器加载⾃⼰的话就会出现⼀些问题,⽐如我们编写⼀个称为 java.lang.Object
类的话,那么程序运⾏的时候,系统就会出现多个不同的 Object 类,⽽有些 Object 类⼜是⽤⼾⾃
⼰提供的因此安全性就不能得到保证了

(五)JVM的垃圾回收

上面说程序计数器,栈的生命周期是和线程有关的,当线程结束时,内存需要跟着线程一起挥手,所以我们现在就来说一下JVM时如何进行垃圾回收的。

   Java堆中存放着⼏乎所有的对象实例,垃圾回收器在对堆进⾏垃圾回收前,⾸先要判断这些对象哪些还存活,哪些已经"死去"。判断对象是否已"死"有如下⼏种算法

如何判断对象不再需要
1)引用计数器

  就是跟名字一样,给对象加一个计数器,如果有地方引用他就会计数器+1,如果引用失效了计数器就-1,任何时刻计数器为0,就说明对象可以被挥手了

   优点:实现简单,方便理解,同时效率较高  缺点:无法解决对象循环引用(类似多线程中的死锁问题)

2)可达性分析

   我们JVM就是通过可达性分析来检测对象是否存活

   核心思想就是遍历,通过根对象作为起始点,从这结点开始向下遍历,走过的路径称为引用链,当一个对象没有任何引用链可以到达时,证明这个对象是不可用的

   比如上图中的object 5和object6 7,虽然她们之间有关联,但是无法由根对象遍历到,所以我们认为它们是不可达的,就会被判定成可回收对象

   在java中可以被当作根对象的有:

1. 虚拟机栈(栈帧中的本地变量表)中引⽤的对象;
2. ⽅法区中类静态属性引⽤的对象;
3. ⽅法区中常量引⽤的对象;
4. 本地⽅法栈中 JNI(Native⽅法)引用的对象

垃圾回收算法
1)标记-清除算法

标记清除就是标记出所有需要回收的对象,在标记完成后统一回收

但是这种算法会导致内存碎片化,也会有效率问题

内存碎片化:标记清除后会产生大量不连续的内存碎片,内存碎片过多会导致我们之后要分配一块连续的空间时,可能无法找到足够的内存

2)  复制算法

   复制算法就是对上述的标记清除算法进行优化,他是将内存分成大小相等的两块,每次只使用其中一边,当这块内存需要垃圾回收时,我们就会将这块区域仍然存活的对象复制到另一边,然后再将这里的内存区域一次性清理,这样既可以提升效率,也可以避免内存碎片化。

  但是仍然有一定的问题,这会导致我们无法充分利用我们的内存,每次都会损失一般的内存空间来复制

3)标记整理算法

    复制算法在面对对象存活率较高的情况下,每次都需要复制很多对象,效率也不会很高,所以在面对对象存活率较高时,我们可以是以哦那个标记整理算法,在刚开始标记无用对象时与标记清除一直,但是之后我们却不是直接删除,而是让所有存活的对象向一端移动,再清理掉边界以外的内存即可

但同时,如果存活元素过多也会有效率问题

4)分代算法

   分代算法是通过区域划分:新生代和老年代,实现不同区域不同策略的垃圾回收机制(当前我们的JVM都是使用分代算法解决垃圾回收机制)。

   新生代中,每次垃圾回收都会有很多对象死去,只有少量存活,我们才用复制算法,而老年代存活对象较多,我们可以采用标记整理或者标记清理算法。

   那什么对象是新生代,什么对象是老年代?

   • 新⽣代(Minor GC):⼀般创建的对象都会进⼊新⽣代;
   • ⽼年代(Full GC):对象经历了 N 次(⼀般情况默认是 15 次)垃圾回收依然存活下来的对象会从新⽣代移动到⽼年代。

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

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

相关文章

2017年国赛高教杯数学建模C题颜色与物质浓度辨识解题全过程文档及程序

2017年国赛高教杯数学建模 C题 颜色与物质浓度辨识 比色法是目前常用的一种检测物质浓度的方法,即把待测物质制备成溶液后滴在特定的白色试纸表面,等其充分反应以后获得一张有颜色的试纸,再把该颜色试纸与一个标准比色卡进行对比&#xff0c…

如何查看电脑什么时候被人动过及看过的文件?

一、查看Windows事件查看器 Windows系统具有强大的日志记录功能,通过“事件查看器”可以查看电脑的使用记录。具体步骤如下: 按下Win R组合键打开运行窗口,输入eventvwr.msc命令并回车,打开事件查看器。 在事件查看器中&#x…

solidwork镜像实体

效果如下: 可以看到这两条线是对称的。 第一步,点击这条要镜像的边,接着点击镜像实体。 然后选择镜像轴,即可

OpenHarmony标准系统mipi摄像头适配

OpenHarmony标准系统mipi摄像头适配 本文档以rk3568为例,讲述如何在OpenHarmony 标准系统rk设备上适配mipi摄像头。 开发环境 OpenHarmony标准系统4.1rrk3568设备摄像头ov5648,ov8858 文档约定:4.1r_3568为OpenHarmony标准系统源码根目录 1.适配准备:得…

苹果CMS插件:优化蜘蛛访问内容,提升百度收录率

确保蜘蛛抓取原始内容 专为苹果CMS设计的广告管理插件,能够智能识别搜索引擎蜘蛛与普通访客,确保蜘蛛访问时展示原始内容,从而提升被百度等搜索引擎收录的几率。 广告显示提升收益 对于普通访客,该插件则优先显示广告内容&#…

UnLua扩展C++函数和蓝图自定义事件

一、通过BlueprintImplementableEvent标记扩展C函数 1、 这个标记表示C不需要实现,让蓝图/Lua重写。 2、首先在C中将LuaImp函数标记为BlueprintImplementableEvent,不需要实现,然后再GetIndex中调用该函数。 MyBaseActor.h UFUNCTION(Bluepr…

电力电塔电线缺陷检测数据集 voc yolo

电力 电塔电线缺陷检测数据集 10000张 带标注 voc yolo 电力电塔电线缺陷检测数据集 数据集描述 该数据集旨在用于电力电塔和电线的缺陷检测任务,涵盖多种常见的缺陷类型。数据集包含了大量的图像及其对应的标注信息,可用于训练计算机视觉模型&#x…

DEPLOT: One-shot visual language reasoning by plot-to-table translation论文阅读

文章链接:https://arxiv.org/abs/2308.01979http://arxiv.org/abs/2212.10505https://arxiv.org/abs/2308.01979 源码链接:https://github.com/cse-ai-lab/RealCQA Abstract 理解图表需要很强的推理能力,之前的最先进 (SOTA&…

圆周阵列元件的间距增加操作方法

在进行器件圆周阵列时,内圈的角度和外圈的旋转角度都相同,由于内圈的圆周长小于外圈的圆周长,有可能在内圈造成部分元件之间有两个焊盘会有覆盖的情况,此时需要对内圈的元件位置进行微调,需要增加在同一半径位置的元件…

数据结构 ——— 算法的时间复杂度

目录 时间复杂度的概念 时间复杂度函数式 大O的渐进表示法的概念 大O的渐进表示法 时间复杂度的概念 在计算机科学中,算法的时间复杂度是一个函数(数学上的函数式),它定量描述了该算法的运行时间,一个算法执行所耗…

Netty笔记10-Netty参数调优

文章目录 一、CONNECT_TIMEOUT_MILLISCONNECT_TIMEOUT_MILLIS设置为1秒超时CONNECT_TIMEOUT_MILLIS设置为5秒超时注意事项 二、SO_BACKLOG代码示例注意事项 三、ulimit -n(文件描述符)设置文件描述符限制在注意事项 四、TCP_NODELAY使用 TCP_NODELAY 的场景注意事项 五、SO_SND…

软件安全最佳实践:首先关注的地方

尽管组织拥有大量可用的工具,但应用程序安全性仍然不足。 最近的数据显示,在过去四到五年中,软件供应链攻击同比增长了 600-700%,超过一半的美国企业在过去 12 个月中遭受过某种形式的软件供应链攻击。 为何应用程序安全工作未…

签署《AI安全国际对话威尼斯共识》 智源持续推动人工智能安全发展

近日,由AI安全国际论坛(Safe AI Forum)和博古睿研究院(Berggruen Institute) 共同举办的第三届国际AI安全对话(International Dialogues on AI Safety)在威尼斯举办。图灵奖得主Yoshua Bengio、姚期智教授&…

电气设备施工现场风险状态判断ai模型训练数据集

电气设备施工现场风险状态判断ai模型训练数据集 id:18 电气设备施工现场工人人工智能学习数据和工作环境安全数据,建立系统化管理体系,改变全球EHS范式,预防工业事故。数据集记录了387709例子电力设施建设以及施工现场相关的灾害安全环境数据…

VM16安装macOS11

注意: 本文内容于 2024-09-17 12:08:24 创建,可能不会在此平台上进行更新。如果您希望查看最新版本或更多相关内容,请访问原文地址:VM16安装macOS11。感谢您的关注与支持! 使用 Vmware Workstation Pro 16 安装 macOS…

数字世界的新秩序:探索Web3的前景

在过去的几十年中,互联网已经彻底改变了我们的生活方式,推动了信息共享、全球互联以及数字经济的快速发展。然而,当前的互联网架构主要是中心化的,由少数大型科技公司控制数据、服务和基础设施。这种模式虽然高效,但也…

Golang | Leetcode Golang题解之第419题棋盘上的战舰

题目: 题解: func countBattleships(board [][]byte) (ans int) {for i, row : range board {for j, ch : range row {if ch X && !(i > 0 && board[i-1][j] X || j > 0 && board[i][j-1] X) {ans}}}return }

微服务注册中⼼2

5.Nacos配置管理 Nacos除了可以做注册中⼼,同样可以做配置管理来使⽤ 5.1 统⼀配置管理 当微服务部署的实例越来越多,达到数⼗、数百时,逐个修改微服务配置就会让⼈抓狂,⽽且很容易出错。我们需要⼀种统⼀配置管理⽅案&#xf…

idea生成类信息及快捷开发配置

目录 一、预言 二、在Java类的开头自动注释作者名字和日期等信息 2.1.各种预设变量 2.2.idea配置 2.3.成品展示 三、快捷开发 3.1.三种循环热键 3.2.if判断 3.3.instanceof运算 3.4.非空判断 3.5.测试打印 3.6. synchronized 3.7.异常抛出 一、预言 在…

Java运算符有哪些?深入解析Java运算符:从基础到进阶的全方位指南(超全表格)

💻1.前言 在编程中,运算符是处理数据和变量的基本工具。它们不仅使得代码更加简洁,还能极大地提高编程效率。本文还提供了详细的 Java运算符参考表格,涵盖了算术运算符、关系运算符、逻辑运算符、赋值运算符、位运算符、…