JVM详解

news/2024/5/18 15:21:54/文章来源:https://blog.csdn.net/weixin_53455615/article/details/126635973

1. 源文件

源文件就是我们编写Java代码的文件。文件扩展名为.java

2. 字节码文件

字节码文件是源文件编译后的文件。字节码文件是二进制文件,需要通过特定的工具才能查看。里面存放了源文件编译后的字节码指令。

3. 类加载器 Class Loader

Java 程序运行时会由类加载器负责把.class的字节码文件装在到内存中,供虚拟机执行。

(1)加载 Loading

  1. 启动类加载器 BootStrap Class Loader

    负责从启动类中加载类。具有最高执行优先级。即:rt.jar等。

  2. 扩展类加载器 Extension Class Loader

    负责加载扩展相关类。即:jre/lib/ext 目录

  3. 应用程序加载器 Application Class Loader

    加载应用程序类路径(classpath)中相关类

(2)链接 Linking

        1.校验 Verify: 校验器会校验字节码文件是否正确。

        2.准备 Prepare: 所有静态变量初始化并赋予默认值

        3.解析 Resolve: 符号引用被换成直接引用。

(3)初始化 Initialization

所有静态变量赋予初值,静态代码块执行。

4. 执行引擎

(1)解释器 Interpreter

解释器负责解释字节码文件。每次方法调用都会被重新解释。

(2)JIT编译器

Java程序在运行的时候,主要就是执行字节码指令,一般这些指令会通过解释器(Interpreter)进行解释执行,这种就是解释执行。

当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为 热点代码。为了提高热点代码的执行效率,在运行时虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler,简称 JIT 编译器)。

(3)探测器

负责探测多次被调用的代码。

(4)垃圾回收器GC

负责回收不在被使用的对象。GC是JVM中非常重要的一块,在后面我们会单独讲解GC。

5. 本地库接口

在Java代码中使用native修饰的方法表示方法具体实现使用其他编程语言实现的。例如:C语言。通过本地库接口为Java程序提供调用其他语言的实现方案。

6. 本地方法库

所有的本地方法,通过本地库接口调用。

7. 程序计数器

程序计数器简称:PC Register

程序计数器是一块较小的内存空间。记录了当前线程执行到的字节码行号。每个线程都有自己的程序计数器,相互不影响。如果是native方法,计数器为空。

8. 虚拟机栈

虚拟机栈跟随线程创建而创建,所以每个线程都有一个虚拟机栈。

虚拟机栈中存储的是栈帧(frames),每个栈帧对应一个方法,每个栈帧都有自己的局部变量表、操作数栈、动态链接和返回地址等。当前正在执行的方法称为当前方法,当前方法所在的帧称为当前帧。方法执行时帧就是一个入栈操作,方法执行完成之后栈帧就是一个出站操作。

(1)局部变量表

局部变量表存储的8大基本数据类型和返回值以及方法参数及对象的引用。 其中long和double占用2倍长度。

局部变量表就是一个数组,数组的长度在编译期确定。通过从0开始的索引调用局部变量表的内容。

对于类方法,从索引0开始连续N个作为方法传递。对于实例方法索引0存储的都是实例化方法的实例fbwqwefwef对象的引用。

(2) 操作数栈

操作数栈存在于栈帧中,其大小在编译期确定。

操作数栈中存储了class文件中虚拟机指令以及准备要传递的参数和接收对方的返回结果。

运行时常量池中数据以及局部变量表中得值都可以由操作数栈进行获取

(3)动态链接

方法·把符号转换为直接引用分为两种情况。

在JVM加载或第一次使用转换时称为静态链接或静态解析。而在运行期间把符号转换为直接引用时就称为动态链接

(4) 方法返回地址

方法返回地址分为两种情况:

1. 正常结束执行。例如碰见return关键字。调用程序计数器的值后当前栈帧直接出栈就可以了。

2. 异常结束。可能需要恢复上层方法的局部变量表和操作数栈,然后把返回值压如到栈帧的操作数栈中,之后调用程序计数器的值后获取到下条指令。

9. 堆

堆是所有线程共享的,存储类的实例和数组。

堆是在虚拟机启动时创建的,由GC负责回收。

堆可以是一块不连续的内存空间。

在Java 8 中,String是存在于堆中的。

堆被分为二大部分:

在Java 7时分为:新生代(Young Generation)、老年代(Old Generation)。在HotSpot中使用永久代来实现方法区的规范。且新生代、老年代和永久代是连续的。

新生代又被分为Eden区、From Survivor区、To Survivor区。官方说明默认分配比例为8:1:1。但是使用jmap工具进行测试时发现比例为6:1:1。

在Java 8时把永久代替换为元空间(MetaSpace),也就是说在Java8中使用元空间来实现方法区。且在Java8中把元空间移植到本地内存上(Native Memory),其实在Java 7 时,部分数据已经移植到本地内存上了。例如:符号引用(Symbols)。

新建对象的存储顺序:新建对象先存储到Eden(伊甸园)区,当Eden区存满之后会触发垃圾回收,然后把没有垃圾回收的对象存储到From Survivor(幸存)区中,当Eden区再次存满时GC会回收Eden区和From区中的垃圾,然后把留下了的对象存储到To Survivor(幸存)区,然后重复上述过程,直到From区或者To区存满之后,就会把对象存到Old(老年)区,当交换次数大于15或者超出存储空间时也会把对象存到Old区。

10. 方法区

方法区是线程共享的。

在虚拟机启动时自动创建方法区,方法区可以是一块不连续的内存空间。 ​方法区可以理解为编译代码存储区。在方法区中存储每个类的结构、运行时常量池、字段、方法、构造方法。

在JVM规范上方法区是一个独立的区域,但是在Java SE7 的HotSpot 上方法区使用永久代作为实现,永久代和堆是一块连续空间。在Java SE8的JVM规范实现上,HotSpot使用元空间实现方法区。

11. GC垃圾回收器

(1)垃圾回收器( garbage collectiongarbage collectiongarbage collection,简称GC)负责回收JVM运行时数据区的堆内存和方法区中数据。而虚拟机栈、程序计数器、本地方法栈都是根据线程创建而创建,随着线程销毁而销毁,所以不需要进行回收。

(2)判断对象是否为垃圾的机制:

1. 引用计数(已淘汰):

引用计数算法就是看对象是否被引用。如果引用则对象计数器加一。如果释放引用计数器减一。但是引用计数算法最大的问题就是循环引用问题。当出现循环引用时对象计数器至少为1.这时候对象可能已经是垃圾了,但是无法被回收。

2 可达性分析:

达可根算法没有引用计数算法中循环引用无法被回收的问题。

其主要思路是通过一系列名为GC Roots的对象作为根,从根开始往下搜索,搜索过程经过的路径称为引用链(Reference Chain),当一个对象到达GC Root时表示当前对象还在使用,如果没有引用的或者和其他非GC Roots循环引用的内容都是垃圾。静态变量、线程变量、常量池、JNI(指针)都是GC Roots。

(3)GC回收算法

1. 标记清除算法(Mark-sweep)

首先标记出所有需要回收的对象。标记完成后统一回收所有标记的对象。

缺点:效率低。碎片多。

2. 标记压缩算法(Mark-Compact)

又叫标记整理算法。和标记清除算法有点类似。主要区别是标记完成后并不会直接清除,而是把所有不回收对象先向一端移动,然后在清除掉边界外面的对象。这样就不会产生内存碎片。

3. 复制算法(coping)

目的:主要是为了解决标记清除算法碎片问题。

步骤:内存按照容量分为大小相等的两块。每次只使用一块。当一块使用完成后,把存活的对象复制到另一个空间,然后把空间一次清除掉。

缺点:可用内存减少。

4. 分代收集算法

把堆分为新生代和老年代。新生代采用一种算法,老年代采用另一种算法。具体新生代和老年代采用的算法需要看使用哪种垃圾回收器。

(4)GC种类

 

(1)Serial、Serial Old 串行收集器

Serial 收集器:起源于JDK 1.3,单线程执行,每次回收必须STW(整个世界都停止,只能垃圾回收的线程执行)。

应用场景:虚拟机在client模式下默认的GC。

优点:简单高效。

Serial Old收集器:老年代收集器。标记整理算法。单线程。主要应用在client模式下老年代收集。在JDK1.5之前可以与Parallel Scavenge配合使用。可作为CMS的备选。

(2)Parallel Scavenge和Parallel Old 收集器

Parallel Scavenge :新生代收集器。采用复制算法。可以并行执行。

优点:具备自适应调节能力。-XX:+UseAdaptiveSizePolicy

主要解决吞吐量问题。也被称为“吞吐量优先”收集器。即吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间),虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。高吞吐量可以高效的利用CPU时间,尽快完成运算任务。

Parallel Old:老年代收集器。标记整理算法。多线程。JDK 1.6中出现。

(3)ParNew收集器

Serial 收集器多线程版本,用于收集新生代。可与CMS配合使用。

ParNew可以并行执行,主要为了减少STW的时间,加快程序响应,给用户提供良好的体验。

(4)CMS收集器

主要为了减少STW时间。

采用标记清除算法:

​初始标记:初始标记只是标记下GC Root能够关联的对象。速度很快。需要STW ​

并发标记:进行GC Roots Tracing的过程 ​

重新标记:修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录

​并发清除:并发的清除对象。

优点:并发收集。低停顿。

缺点: 对CPU非常敏感,对于CPU大于4个时要求并发收集时使用的线程数不等于1/4。但随着CPU增加而下降。 可能产生浮动垃圾。因为CMS清理阶段程序还在运行,所以就可能产生新的垃圾,这部分垃圾只能等到下次才能被清理。所以称为浮动垃圾。 ​ 可能产生大量空间碎片。

(5)G1收集器(garbage-first)

JDK8中主推的收集器。属于CMS的替代品。 ​G1收集器时堆中的年轻代和老年代只是逻辑上的概念,实际上把堆(一块连续内存)分为很多Region(分区)每个分区里面又被分为多个卡片(Card)。所以里面可能有很多年轻代和老年代。G1收集器里面多了一个新的概念:humongous(巨型对象)。当对象达到或超过Region一半时称为巨型对象。巨型对象独占一个或多个连续的Region。

  1. 初始标记:初始标记阶段仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS(Next Top at Mark Start)的值。此过程需要STW,但是耗时很短。

  2. 并发标记:并发标记阶段是从GC Root开始对堆中对象进行可达性分析,找出存活的对象。此过程耗时可能较长于用户操作并发执行,不需要STW。

  3. 最终标记。标记因为并发标记时用户执行产生的垃圾。需要STW(也可以并行)

  4. 筛选回收。对各个Region收回价值和时间进行计算,筛选出符合用户设定的预期回收时间。

(6) G1收集器和CMS收集器的区别

  1. G1是用在新生代和老年代同时使用。CMS是老年代收集器。

  2. G1是Java8主推的收集器。CMS是java5出现的收集器。

  3. G1的STW时间可由用户设定,在筛选回收过程“可预测”的想办法满足设定要求。CMS是尽可能的减少STW时间

  4. G1使用的是标记整理算法,CMS使用的是标记清除算法(所以可能有内存碎片)。

  5. G1回收的流程是初始标记、并发标记、最终标记、筛选回收。CMS的流程是:初始标记、并发标记、重新标记、并发清除。

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

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

相关文章

USB转GPIO应用方案

概述 沁恒提供的多款USB转接系列芯片均提供GPIO引脚功能,各引脚支持独立的输出输入,GPIO功能的使用需要与计算机端厂商驱动程序和应用软件配合使用。各芯片的默认GPIO引脚状态有所区别,可查阅芯片技术手册或参考方案中附表。 型号 CH344Q …

基于神经网络的图像识别,人工神经网络图像识别

如何通过人工神经网络实现图像识别 。 人工神经网络(ArtificialNeuralNetworks)(简称ANN)系统从20世纪40年代末诞生至今仅短短半个多世纪,但由于他具有信息的分布存储、并行处理以及自学习能力等优点,已经…

Jmeter(五) - 从入门到精通 - 测试计划(Test Plan)的元件(详解教程)

一.测试计划(Test Plan)要素 1.JMeter中一个脚本就是一个测试计划(Test Plan),也是一个管理单元。JMeter 的请求模拟与并发数(设置线程数,一个线程代表一个虚拟用户)设置都在脚本文件中一起设置。JMeter 不…

雨夜赶长路,房企必经的三场“价值战事”

今年上半年,地产行业一直在高压下运行。市场周期震荡叠加疫情等因素,为房企的销售、土拍、融资带来不确定性。 下半年以来,虽然不确定性和高压仍在,但市场有望恢复,下行趋势似乎已到拐点。 面对高压,不同…

安装 ZooKeeper 并配置服务

官网 访问官方下载页面安装 # 注意替换一下新的链接 curl -sSLO https://dlcdn.apache.org/zookeeper/zookeeper-3.8.0/apache-zookeeper-3.8.0-bin.tar.gz tar -zxvf apache-zookeeper-3.8.0-bin.tar.gz -C /opt/ cd /opt ln -s zookeeper-3.4.10 ./zookeepercd zookeeper m…

微服务项目:尚融宝(8)(后端接口:积分等级CRUD)

认清现实,放弃幻想,准备斗争 一、积分等级列表接口 1、编写积分等级管理接口 在controller中添加admin包,添加AdminIntegralGradeController类CrossOrigin RestController RequestMapping("/admin/core/integralGrade") public cl…

Mac中无法运行旧版本印象笔记:版本太旧 你的本地印象笔记数据是由新版印象笔记管理

📢📢📢📣📣📣 哈喽!大家好,我是「奇点」,江湖人称 singularity。刚工作几年,想和大家一同进步🤝🤝 一位上进心十足的【Java ToB端大厂…

算法设计与分析作业——递归循环

用循环实现&#xff1a; 1、 求级数 求&#xff1a;1/1!-1/3!1/5!-1/7!…(-1)n1/(2n-1)! #include <bits/stdc.h> using namespace std; int main( ) {int i,n,j,sign1; float s,t1; cin>>n; s1; for(i2;i<n;ii1){t1; /*求阶乘*/for(j1;j<2*i-1;…

(11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】

&#xff08;1&#xff09;工业界推荐系统-小红书推荐场景及内部实践【业务指标、链路、ItemCF】 &#xff08;2&#xff09;工业界推荐系统-小红书推荐场景及内部实践【UserCF、离线特征处理】 &#xff08;3&#xff09;工业界推荐系统-小红书推荐场景及内部实践【矩阵补充、…

推荐10款好用的数据可视化工具,赶紧收藏

写在前面的话&#xff1a;没有十全十美的工具&#xff0c;但是如果确立&#xff08;可视化&#xff09;目标&#xff0c;就能找到合适的工具去实现。 数据分析过程可以分为&#xff1a;确定目标数据、数据采集、数据清洗、数据存储、数据分析、结果可视化及结果支持和决策等步骤…

文字转音频软件哪个好用?这几个方法你值得拥有

不知道你有没有发现一个现象&#xff0c;现在越来越多的人会把自己制作好的视频发布到各个社交平台上&#xff0c;分享自己的日常。有的人还会用自己的声音来做配音旁白&#xff0c;而有的人因为自己声音和视频不搭&#xff0c;会使用配音软件&#xff0c;把文字转换成语音。可…

FRED应用:真实玻片设置

简介 FRED具备通过光学系统模拟光线偏振的能力。光源可以是随机偏振、圆偏振或线偏振。过滤或控制偏振的光学元件&#xff0c;如双折射波片和偏振片&#xff0c;可以准确的模拟。FRED偏振模型中一些简单例子包括吸收二向色性和线栅偏振片&#xff0c;方解石半波片&#xff0…

最近在学日语

对比了一些B站的日语教学视频,觉得这个挺不错: 视频在这里昨天开始学的,50音图平假名全记住了,片假名还有点磕巴。 现在开始学语法了。 【动力这种东西,真是来得莫名奇妙。】手打一遍50音图,练习~ (键盘手打刻意练习了一下,熟练多了。) a i u e o あ ア い イ う…

Magisk如何针对性隐藏Root避免被检测

如果这篇文章对你有帮助,欢迎点赞关注收藏三联,这对我有帮助,谢谢小伙伴们,你们的支持是我认真分享的动力。 关于Magisk有一个有趣的故事,Magisk的作者老吴,国内人,妥妥的大牛,主攻Root领域,目前在Google里卖弄当工程师,在去Google之前,老吴还去苹果公司实习过,就在…

HTML5新特性 day_05(8.11)上传头像、webSocket

一、文件上传经典业务流程 -- 上传头像 在注册业务&#xff0c;填写表单的过程中&#xff0c;需要选择头像&#xff0c;上传头像&#xff0c;填写基本信息&#xff08;用户名、密码等&#xff09;后&#xff0c;点击注册按钮&#xff0c;完成用户注册。当下次登录时需要看到以…

janus videoroom之媒体录制

janus videoroom为音视频会议&#xff0c;内部自创建一个房间号为1234的会议&#xff0c;读者可以配置会议召开时&#xff0c;录制会议的视频和语音&#xff0c;录制文件的后缀名为mjr&#xff0c;此为janus自定义的一种媒体封装格式&#xff0c;个人理解全称是meetecho janus …

我换了一圈儿,又回来了!

C语言 C语言应该很多人都学过&#xff0c;因为计算机、电子通信、自动化一类的专业基本上都要学习它。 然而&#xff0c;学习的人多&#xff0c;但用它来实际开发项目的人却少之又少。 这是为什么呢&#xff1f; 在我看来&#xff0c;主要有两个原因。 第一&#xff0c;难度…

配置dns服务的正反向解析

服务端 安装包 dnf install bind bind-utils -y systemctl stop firewalld.service 关闭防火墙 setenforce 0 关闭selinux vim /etc/named.conf 配置内容 options { listen-on port 53 { 192.168.182.129; }; directory “/var/named”; allow-query { any; }; }; zone …

Android中Spi机制的使用及源码原理解析

使用 定义接口 public interface IFunctionService {void test(); }定义接口实现,这里实现了三个实现类。 public class FunctionService1 implements IFunctionService {private static final String TAG "FunctionService1";Overridepublic void test() {Log.e(…

Shader Graph的用法初探

简单有深度的东西可以用Shader&#xff0c;但酷炫的效果离不开这个好用东西。 参考文章&#xff1a;unity shader可视化工具——Shader Graph Unity ShaderGraph使用教程与各种特效案例&#xff1a;Unity2022 我自己装了两个包shader Graph和Universal RP&#xff0c;&#x…