JVM重点

news2024/9/20 18:49:55

文章目录

  • 0. 运行流程
  • 1. 内存区域划分
    • 1.1 堆
    • 1.2 Java 虚拟机栈
    • 1.3 程序计数器
    • 1.4 方法区
  • 2. 类加载机制
    • 类加载过程
    • 2.1 加载
    • 2.2 验证
    • 2.3 准备
    • 2.4 解析
    • 2.5 初始化
    • 双亲委派模型
  • 3. 垃圾回收机制
    • 3.1 垃圾判断算法
      • 3.1.1 引用计数算法
      • 3.1.2 可达性分析算法
    • 3.2 垃圾回收算法
      • 3.2.1 标记清除算法
      • 3.2.2 复制算法
      • 3.2.3 标记整理算法
      • 3.2.4 分代算法
    • 3.3 垃圾收集器

0. 运行流程

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

1. 内存区域划分

如图:
内存划分

1.1 堆

程序中创建的所有对象都保存在堆中。
堆中又可以划分为两个部分,新生代和老生代。
新生代为新创建的对象,当经过一定 GC(下面讲) 次数之后还存活的对象
会放入老生代。
而新生代还有 3 个区域:一个 Endn + 两个 Survivor(from/to | s0/s1)。
垃圾回收的时候会将 Endn 中存活的对象放到一个未使用的 Survivor 中,并把当前的 Endn 和正在使用的 Survivor 清楚掉。
在这里插入图片描述

1.2 Java 虚拟机栈

Java 虚拟机栈的作用:Java 虚拟机栈的生命周期和线程相同,Java 虚拟机栈描述的是 Java 方法执行的。
内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。咱们常说的堆内存、栈内存中,栈内存指的就是虚拟机栈。
栈

  1. 局部变量表: 存放了编译器可知的各种基本数据类型(8大基本数据类型)、对象引用。局部变量表 所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在执行期间不会改变局部变量表大小。简单来说就是存放方法参数和局部变 量。
  2. 操作栈:每个方法会生成一个先进后出的操作栈。
  3. 动态链接:指向运行时常量池的方法引用。
  4. 方法返回地址:PC 寄存器的地址。

本地方法栈和虚拟机栈类似,只不过 Java 虚拟机栈是给 JVM 使用的,而本地方法栈是给本地方法使用的。

1.3 程序计数器

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

1.4 方法区

方法区的作用:用来存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据的。
在《Java虚拟机规范中》把此区域称之为“方法区”,而在 HotSpot 虚拟机的实现中,在 JDK 7 时此区域叫做永久代(PermGen),JDK 8 中叫做元空间(Metaspace)。

题

2. 类加载机制

JVM执行流程中对程序员来说最重要的就是类加载的流程,对于类来说,它的生命周期如图:
类
而类加载的流程就是前五步。

类加载过程

2.1 加载

加载”(Loading)阶段是整个“类加载”(Class Loading)过程中的一个阶段,它和类加载 Class Loading 是不同的,一个是加载 Loading 另一个是类加载 Class Loading,所以不要把二者搞混了。
在加载 Loading 阶段,Java虚拟机需要完成以下三件事情:

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

通俗点就是: 找到.class文件,打开文件,读取文件内容,并且尝试解析格式。

2.2 验证

验证是连接阶段的第一步,这一阶段的目的是确保Class文件的字节 流中
包含的信息符合《Java虚拟机 规范》的全部约束要求,保证这些信 息被当作代码运行后不会危害虚拟机自身的安全。
验证当前.class文件的格式,是否符合要求。
验证选项:

  • 文件格式验证
  • 字节码验证
  • 符号引用验证…

2.3 准备

准备阶段是正式为类中定义的变量(即静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段,。
给类对象分配空间,内容全是0.

2.4 解析

解析阶段是 Java 虚拟机将常量池内的符号引用(相对位置)替换为直接引用(真实位置)的过程,也就是初始化常量的过程。
主要是初始化类对象中涉及的字符串常量,但其实.class文件中含有,直接读取到内存即可。

2.5 初始化

初始化阶段,Java 虚拟机真正开始执行类中编写的 Java 程序代码,将主导权移交给应用程序。
初始化阶段就是执行类构造器方法的过程。

双亲委派模型

描述类加载的过程,如何找到.class文件。
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最 终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无 法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。
而JVM带有三个类加载器(也可以自己写新的类加载器),从上到下依次是BootStrap ClassLoader(负责加载标准库中的类)——>Extension ClassLoader(负责加载扩展库中的类)——>Application ClassLoader(负责加载第三方库中的类;例如: servlet,自己写的类……)。

3. 垃圾回收机制

上面讲了Java运行时内存的各个区域。对于程序计数器、虚拟机栈、本地方法栈这三部分区域而言,其生命周期与相关线程有关,随线程而生,随线程而灭。并且这三个区域的内存分配与回收具有确定性,因为当方法结束或者线程结束时,内存就自然跟着线程回收了。因此我们所讲的有关内存分配和回收关注的为Java堆与方法区这两个区域。

3.1 垃圾判断算法

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

  • 引入计数
  • 可达性分析

3.1.1 引用计数算法

给对象增加一个引用计数器,当有一个对象引用它,计数器加1,引用消失,计数器减1,当引用计数器为0,就判断对象为垃圾。
python采用引用计数法管理内存。
但这种算法有着很大的问题,所以Java JVM中不使用这种方法。
缺点

  1. 浪费内存,如果对象很小,内存浪费很严重。
  2. 在对象循环引用时,可能会有问题。
    两个对象中都引用对方,两者引用计数器都为2,当使两个对象为空,-1,但是引用计数器为1,这样就会出现这两个对象已经为垃圾,但是没有收集。

3.1.2 可达性分析算法

而Java中使用的是可达性分析算法,判断对象是否为垃圾。这个算法的起点是“GC Roots”,即一组被认为是Java虚拟机中的根对象。Java虚拟机会遍历这些根对象,找到它们所引用的对象,将这些对象标记为“存活”。当一个对象到GC Roots没有任何引用链相连,即从GC Roots到这个对象不可达,则证明此对象是不可用,就表示可回收的对象。
类似于树,有一个根对象,后面的对象都被其他对象引用,当前面的对象消失,这个对象后引用的对象也会消失。

3.2 垃圾回收算法

通过上面的学习我们可以将死亡对象标记出来了,标记出来之后我们就可以进行垃圾回收操作了,在正式学习垃圾收集器之前,我们先看下垃圾回收机器使用的几种算法(这些算法是垃圾收集器的指导思想)。

3.2.1 标记清除算法

"标记-清除"算法是最基础的收集算法。算法分为"标记"和"清除"两个阶段 : 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象(标记过程见3.1.2章节)。后续的收集算法都是基于这种思路并对其不足加以改进而已。
"标记-清除"算法的不足主要有两个 :

  1. 效率问题 : 标记和清除这两个过程的效率都不高
  2. 空间问题 : 标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行中 需要分配较大对象时,无法找到足够连续内存而不得不提前触发另一次垃圾收集。

如图:标记清除

3.2.2 复制算法

"复制"算法是为了解决"标记-清理"的效率问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后再把已经使用过的内存区域一次清理掉。这样做的好处是每次都是对整个半区进行内存回收,内存分配时也就不需要考虑内存碎片等复杂情况,只需要移动堆顶指针,按顺序分配即可。此算法实现简单,运行高效。
算法的执行流程如下图 :
在这里插入图片描述
但是缺点也很明显:

  1. 浪费了一半内存。
  2. 效率低,容易出现STW。
    STW是指Java虚拟机在执行垃圾回收(GC)时的一种状态,即Stop-The-World。在STW状态下,Java应用程序的所有线程都将被暂停执行,只有GC线程除外。

3.2.3 标记整理算法

复制收集算法在对象存活率较高时会进行比较多的复制操作,效率会变低。因此在老年代一般不能使用复制算法。
针对老年代的特点,提出了一种称之为"标记-整理算法"。标记过程仍与"标记-清除"过程一致,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。
流程图如下:
2

3.2.4 分代算法

前面我们知道JVM堆中对象分为新生代和老年代。这就是为GC做的,Java中使用的垃圾回收算法就是分代算法。
新生代:一般创建的对象都会进入新生代;
老年代:大对象和经历了 N 次(一般情况默认是 15 次)垃圾回收依然存活下来的对象会从新生代移动到老年代。
在新生代中,每次垃圾回收都有大批对象死去,只有少量存活,因此我们采用复制算法;而老年代中对象存活率高、没有额外空间对它进行分配担保,就必须采用"标记-清理"或者"标记-整理"算法。
这样我们只需要经常扫描新生代,老年代扫描间隔相对新生代大10倍以上。
请问了解Minor GC和Full GC么,这两种GC有什么不一样吗

  1. Minor GC又称为新生代GC : 指的是发生在新生代的垃圾收集。因为Java对象大多都具备朝 生夕灭的特性,因此Minor GC(采用复制算法)非常频繁,一般回收速度也比较快。
  2. Full GC 又称为 老年代GC或者Major GC : 指发生在老年代的垃圾收集。出现了Major GC, 经常会伴随至少一次的Minor GC(并非绝对,在Parallel Scavenge收集器中就有直接进行 Full
    GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上。

3.3 垃圾收集器

上面讲的都是垃圾收集的思想,而我们垃圾收集器则是具体的实现。
作用
垃圾收集器是为了保证程序能够正常、持久运行的一种技术,它是将程序中不用的死亡对象也就是垃圾对象进行清除,从而保证了新对象能够正常申请到内存空间。
下面收集器是不同时代推出的不同的垃圾收集器,它们有的已经淘汰,有的仍在时候,它们具有不同的优缺点。
了解了解即可。
在这里插入图片描述

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

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

相关文章

01 # 手写 new 的原理

new 做了什么? 在构造器内部创建一个新的对象这个对象内部的隐式原型指向该构造函数的显式原型让构造器中的 this 指向这个对象执行构造器中的代码如果构造器中没有返回对象,则返回上面的创建出来的对象 手写 new 的过程 new 是一个运算符,只能通过函…

Redis Cluster高可用集群原理

目录 一、Redis Cluster和哨兵对比二、槽位定位算法三、集群节点间的通信机制四、集群选举原理五、网络抖动六、Redis集群为什么至少需要三个master节点,并且推荐节点数为奇数?七、集群没有过半机制会出现脑裂数据丢失问题八、跳转重定位九、集群对批量操…

封神工具:腾讯云服务器价格计算器,精准报价一键计算!

腾讯云服务器价格计算器可以一键计算出云服务器的精准报价,包括CVM实例规格价格、CPU内存费用、公网带宽收费、存储系统盘和数据盘详细费用,腾讯云百科txybk.com分享腾讯云价格计算器链接入口、使用方法说明: 腾讯云服务器价格计算器 打开腾…

行业追踪,2023-10-25

自动复盘 2023-10-25 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…

[奇奇怪怪符号]输入法手动输入希腊字母

日常写材料总要输入一些奇奇怪怪符号,虽然知道有一张表,可以在上面选,但是在文本编辑器上找到并打开也不是一件容易的事情,(功能多的编辑器就很臃肿,令人眼花缭乱的标签) 很想要简洁的编辑器&a…

文件加密软件(2023十大文件加密软件排行榜)

文件加密软件已成为企业和个人保护文件安全的重要工具。本文将介绍2023年十大文件加密软件的排行榜,以帮助大家了解和选择适合自己的文件加密软件。 本文是根据软件的功能性、安全性、易用性和创新性等多方面指标进行评选,以体现各大文件加密软件的实力和…

C++多态的认识与理解

多态的概念 通俗来说,多态就是多种形态。具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。 比方说买高铁票时,如果你是学生的话,买票就有优惠。如果你是军人的话,就可以优先买票。普通人的话&…

聚观早报 |2024年春节连休8天;RTE2023开幕

【聚观365】10月26日消息 2024年春节连休8天 RTE2023开幕 一加12首发“东方屏” 微软公布2024财年第一财季财报 Alphabet Q3业绩好于预期 2024年春节连休8天 国务院办公厅发布关于2024年部分节假日安排的通知。2024年春节,2月10日至17日放假调休,共…

Linux ———— 用户-组

Linux是一个多用户多任务的操作系统。 用户(user): 在Linux系统中,用户是一个拥有独立空间、权限和身份的实体。每个用户都有一个唯一的用户名和用户ID。用户可以登录到系统、读取、写入、执行文件,并按照预设的权限进…

Pytorch使用torch.utils.data.random_split拆分数据集,拆分后的数据集状况

对于这个API,我最开始的预想是从 猫1猫2猫3猫4狗1狗2狗3狗4 中分割出 猫1猫2狗4狗1 和 猫4猫3狗2狗3 ,但是打印结果和我预想的不一样 数据集文件的存放路径如下图 测试代码如下 import torch import torchvisiontransform torchvision.transforms.Compose([torchvision.tran…

算法通关村-黄金挑战K个一组反转

大家好我是苏麟 , 今天带来K个一组反转 , K个一组反转 可以说是链表中最难的一个问题了,每k 个节点一组进行翻转,请你返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后…

索引模型的常见数据结构

索引的出现是为了提高查询效率,三种常见、也比较简单的数据结构 哈希表有序数组搜索树 哈希表 哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的键即 key,就可以找到其对应的值即 Value。哈希的思路很简单…

Python实验项目4 :面对对象程序设计

1:运行下面的程序,回答问题。 (1)说明程序的执行过程; (2)程序运行结果是什么? # (1)说明程序的执行过程; # (2)程序运行…

Python在不同场景下的并发编程方案选择

目录 一、多线程 二、多进程 三、异步IO 四、优缺点分析 五、注意事项 总结 并发编程是软件开发中的重要一环,它允许程序同时处理多个任务,提高程序的运行效率和响应速度。Python作为一种流行的编程语言,提供了多种并发编程方案。 一、…

source insight 使用过程中问题点总结

1. //1 //2 不现实大小的注释。选中Special comment styles即可。

vector详解

迭代器 vector维护的是一个连续线性空间。普通指针可以满足条件作为vector的迭代器。 template <typename T, typename Allocalloc> class vector { public: using value_type T; using iterator value_type*; }; vector::iterator //int* vector::iterator //char* …

HFP协议分析

HFP 全称为Hands-Free Profile&#xff0c;通俗的说就是蓝牙电话协议&#xff0c;可以通过指定好的AT command来控制通话的接听、挂断、拒接等 看协议的一些约定格式 在HFP协议文档里面有一个约定&#xff0c;这里贴出来&#xff0c;每种不同的标识代表不同的意思&#xff0c…

2023年中国高尔夫用品产值、市场规模及细分产品现状分析[图]

高尔夫用品市场是指个人的高尔夫用品&#xff0c;主要包括高尔夫球具、高尔夫球包、高尔夫用球、高尔夫服装、高尔夫鞋、高尔夫帽子、高尔夫手套及相关配件等方面。 随着高尔夫产业的逐步兴起&#xff0c;高尔夫运动受到了越来越多人们的青睐&#xff0c;与此同时&#xff0c;也…

Loop Copilot:AI驱动,小白也能自己生成音乐?

01 项目介绍 Loop Copilot是一个使用自然语言生成音乐的系统。它不仅允许你使用自然语言来生成你想要的音乐风格、节奏或旋律&#xff0c;还支持通过多轮对话对已生成的音乐进行进一步的编辑和修改。包括对生成的音乐进行编辑修改、添加或删除乐器、加入音效等。 02 工作流程…

0027Java程序设计-房屋出租管理系统

文章目录 摘 要目 录系统设计开发环境 摘 要 随着我国市场经济的快速发展和人们生活水平的不断提高&#xff0c;简单的房屋出租服务已经不能满足人们的需求。如何利用先进的管理手段&#xff0c;提高房屋出租的管理水平&#xff0c;是当今社会所面临的一个重要课题。 本文采用…