JVM(java虚拟机 详解三个主要的话题:1.JVM 中的内存区域划分2.JVM 的类加载机制3.JVM 中的垃圾回收算法)

jdk  java开发工具包

jre  java运行时环境

jvm java虚拟机

JDK、JRE、JVM之间的关系?
JDK(Java Development Kit):Java开发工具包,提供给Java程序员使用,包含了JRE,同时还包含了编译器javac与自带的调试工具Jconsole、jstack等。
JRE(Java Runtime Environment):Java运行时环境,包含了JVM,Java基础类库。是使用Java语言编写程序运行的所需环境。
JVM:Java虚拟机,运行Java代码

java语言的顺序:

1.使用记事本或者IDEA(集成开发环境)编写Java源程序
2.使用javac.exe编译器编译Java源程序,生成xxx.class的字节码文件 语法格式:javac xxx.java

3.使用java运行xxx.class字节码文件 语法格式:java xxx

因此, 我们编写和发布一个 java 程序,其实就只要发布 .class 文件即可jvm 拿到 .class 文件,就知道该如何转换.windows 上的 jvm 就可以把 .class 转成 windows 上能支持的可执行指令了linux 上的 jvm 就可以把 .class 转成 linux 上可以支持的可执行指令了!

三个主要的话题:

1.JVM 中的内存区域划分
2.JVM 的类加载机制
3.JVM 中的垃圾回收算法


JVM 中的内存区域划分

JVM其实也是进程

在任务管理器中可以看到

进程运行的前期,需要向系统申请一些资源(内存就是其中典型的资源)

这些内存就支撑了后续的java程序的执行.

比如:在java中定义变量所消耗的内存,就是jvm从系统中申请的内存.

jvm从系统中要了一些内存之后,又会根据实际的内存来分批不同的空间来存放不同的数据.(这个就是区域划分).

此处谈到的堆和栈和数据结构中谈到的堆和栈是不同的.

堆:

代码中new出来的对象都是在这里,对象中持有的非静态变量也在这里.

栈:

1.本地方法栈:jvm内部通过c++写的底层逻辑,调用关系和局部变量(一般不会谈到这,说到栈都是说的是栈的虚拟机栈)

2.虚拟机栈:记录了java中方法的调用关系,java代码的局部变量.

每个线程都有自己的栈和计数器

程序计数器:

这个区域比较小的空间,专门存储下一条java指令要执行的地址.(每个线程都有自己的程序计数器和栈)

元数据区(以前java中叫做方法区,从1.8开始改名字):

指的是一些有辅助性质的,描述性质的属性.

咱们写的 java 代码, if, while, for, 各种逻辑运算..这些操作最终都会被转换成 java 字节码
(javac 就会完成上述代码=>字节码)
此时这些字节码在程序运行的时候就会被jvm 加载到内存中放到 元数据区(方法区) 里头
此时,当前程序要如何执行,要做哪些事情,就会按照上述元数据区里记录的字节码依次执行了.

就类似硬盘一样


JVM的类加载机制

类加载大体的过程可以分成5 个步骤(也有资料上说是 3 个,这个情况就是把 2,3,4 合并成一个了)

1.加载

把硬盘上的.class文件找到,然后打开文件,然后读取文件内容.(认为读到的是二进制数据)

2.验证

需要验证当前内容是合法的,是.class(字节码文件)格式

3.给类对象申请空间

此处申请的内存空间.值都是默认0

4.解析

主要是针对字符串常量处理.

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

将符号偏移量转换为直接引用hello的地址就是解析

5.初始化

还要执行静态代码块的逻辑.还可能触发父类的加载.


加载环节(双亲委派模型):描述了如何查找.class的文件策略.

JVM 中进行类加载的操作,是有一个专门的模块,称为"类加载器"(ClassLoader)JM 中的类加载器默认是有 三个 的.(也可以自定义)

上述这三个类型存在父子关系.从下到上.

双亲委派模型工作过程:
1.从 ApplicationClassLoader 作为入口,先开始工作
2.ApplicationClassLoader 不会立即搜索自己负责的目录会把搜索的任务交给自己的父亲,
3.代码就进入到 ExtensionClassLoader 范畴了ExtensionClassLoader 也不会立即搜索自己负责的目录也要把搜索的任务交给自己的父亲
代码就进入到 BootstrapClassLoader 范時了BootstrapClassLoader 也不想立即搜索自己负责的目录也要把搜索的任务交给自己的父亲
5. BootstrapClassLoader 发现自己没有父亲才会真正搜索负责的目录(标准库目录)
通过全限定类名,尝试在标准库目录中找到符合要求的 .class 文件
如果找到了,接下来就直接进入到打开文件/读文件等流程中,如果没找到,回到孩子这一辈的类加载器中,继续尝试加载,
6.ExtensionClassLoader 收到父亲交回给他的任务之后,
自己进行搜索负责目录(扩展库的目录)
如果找到了,接下来进入到后续流程.
如果没找到,也是回到孩子这一辈的类加载器中继续尝试加载,
7.ApplicationClassLoader 收到父亲交回给他的任务之后自己进行搜索负责的目录(当前项目目录/第三方库目录)
如果找到了,接下来进入后续流程.
如果没找到,也是回到孩子这一辈的类加载器中继续尝试加载.由于默认情况下 ApplicationClassLoader 没有孩子了,此时说明类加载过程失败了!就会抛出 ClassNotFoundException 异常

JVM垃圾回收机制(GC)

c++就没有这样的机制,不是因为这个机制很难实现,而是因为这个东西会额外的付出系统开销.影响程序的执行性能.

java发展多年,可以把垃圾回收处理控制在1ms内.一个请求或者接受时间一般是几ms到几十ms.

如果一个引用没有任何指向,就说明所有的指向都结束了,就是荒废的引用.就可以进行回收了.

如果代码比较复杂,这样就解决不了了,就有了以下两中办法:

1.引用计数

这种方法没有在java中使用,但是在别的语言中广泛使用(比如python,PHP等等)

给每个对象安排一个小空间,用来记录当前对象有几个引用.

2.可达性分析(JVM用的是这个)

本质上是用"时间 换 空间”相比于引用计数,需要消耗更多的额外的时间, 但是总体来说,还是可控的.
不会产生类似于"循环引用"这样的问题.
在写代码的过程中,会定义很多的变量.
比如,栈上的局部变量/方法区中的静态类型的变量/常量池中引用的对象!....
就可以从这些变量作为起点,出发,尝试去进行"遍历"所谓的遍历就是会沿着这些变量中持有的引用类型的成员,再进一步的往下进行访问...
所有能被访问到的对象,自然就不是垃圾了.剩下的遍历一圈也访问不到的对象,自然就是垃圾~~


识别出垃圾以后,还需要释放垃圾:

主要的释放方式有三种:

a.标记-清除(一般不会用这个方法,因为内存碎片问题,比较致命)

比如黑色的就是垃圾,此时我们直接释放,就会产生很多小的内存碎片,就会导致后续的内存申请失败

因为内存申请是一片连续的空间.

b.复制算法

c.标记-整理

类似于顺序表删除中间元素.(搬运)


分代回收(依据不同种类的对象,采取不同的方式)
引入概念, 对象的年龄,
JM 中有专门的线程负责周期性扫描/释放,一个对象,如果被线程扫描了一次,可达了(不是垃圾),年龄就 +1(初始年龄相当于是 0)
JVM 中就会根据对象年龄的差异,把整个堆内存分成两个大的部分新生代(年龄小的对象)/ 老年代(年龄大的对象)

1)当代码中 new 出一个新的对象,这个对象就是被创建在伊甸区的.伊甸区中就会有很多的对象
.个经验规律: 伊甸区中的对象,大部分是活不过第一轮 GC这些对象都是"朝生夕死”,生命周期非常短!!

2)第一轮 GC 扫描完成之后,少数伊甸区中幸存的对象, 就会通过复制算法, 拷贝到 生存区后续 GC 的扫描线程还会持续进行扫描,不仅要扫描伊甸区,也要扫描生存区的对象.生存区中的大部分对象也会在扫描中被标记为垃圾.少数存活的,就会继续使用复制算法,拷贝到另外一个生存区中!!只要这个对象能够在生存区中继续存活,就会被复制算法继续拷贝到另一半的生存区中.每次经历一轮 GC 的扫描,对象的年龄都会 +1

3)如果这个对象在生存区中,经过了若干轮 GC 仍然健在~~JVM 就会认为,这个对象生命周期大概率很长, 就把这个对象从生存区,拷贝到老年代~~


4)老年代的对象,当然也要被 GC 扫描,但是扫描的频次就会大大降低了
老年代的对象,要 G 早 G 了~~ 既然没 G 说明生命周期应该是很长的,频繁 GC 扫描意义也不大,白白浪费时间.不如放到老年代,降低扫描频率,


5)对象在老年代寿终正寝,此时 JM 就会按照标记整理的方式,释放内存!

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

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

相关文章

【Java】实现一个简单的线程池

📝个人主页:哈__ 期待您的关注 一、线程池的模式 线程池顾名思义就是管理线程的一个池子,我们把创建线程的过程交给线程池来处理,而这个线程池当中的线程都会从阻塞队列当中取获取任务执行。 我们不在直接把任务的创建过程写到…

【信号与系统 - 10】拉普拉斯变换

1 定义 周期信号的傅里叶变换那篇提到了&#xff1a; F ( j w ) ∫ − ∞ ∞ e − j w t f ( t ) d t F(jw)\int^{\infty}_{-\infty}e^{-jwt}f(t)dt F(jw)∫−∞∞​e−jwtf(t)dt 这个定义式需要满足绝对可积&#xff0c;即 ∫ − ∞ ∞ ∣ f ( t ) ∣ d t < ∞ \int…

小图标还不会设计!

ICON图标设计 hello&#xff0c;我是小索奇 image-20230805225451447 你有好奇过这样的图标如何设计的吗&#xff1f; 其实非常简单&#xff0c;仅需要一行代码即可完成&#xff0c;本篇文章就带伙伴们使用&#xff0c;每天看一篇&#xff0c;简单易懂&#xff0c;日久技长~…

MATLAB实现图片栅格化

MATLAB实现图片栅格化 1.读取图片&#xff1a;首先&#xff0c;你需要使用imread函数读取要栅格化的图片。 2.设置栅格大小&#xff1a;确定你希望将图片划分成的栅格大小&#xff0c;即每个栅格的宽度和高度。 3.计算栅格数量&#xff1a;根据图片的总尺寸和栅格大小&#…

应对.halo勒索病毒:如何应对并保护你的数据安全?

导言&#xff1a; 在数字化时代的今天&#xff0c;网络空间已成为人们生活和工作中不可或缺的一部分。然而&#xff0c;随着网络的普及和技术的不断进步&#xff0c;网络安全问题也日益凸显。其中&#xff0c;勒索病毒作为一种极具破坏性的网络攻击手段&#xff0c;已经引起了…

【Linux】小知识点温习---命令

许多常见命令会用&#xff0c;但是很少注意他们的区别&#xff1b;亦或在学习中使用较少&#xff0c;容易忘记&#xff0c;今天做一个回顾。 ls系列 -a:显示所有文件&#xff08;包括隐藏文件&#xff09; -l:将文件以竖列形式显示 -i&#xff1a;显示文件的inode编号 pwd 显…

盲盒一番赏小程序:打开未知的惊喜之旅

在快节奏的生活中&#xff0c;人们总是渴望寻找一份属于自己的小确幸。盲盒一番赏小程序&#xff0c;正是这样一个为你带来无尽惊喜与乐趣的平台。我们精心打造这一小程序&#xff0c;让每一次点击都成为一次全新的探索&#xff0c;让每一次选择都充满无限可能。 盲盒一番赏小…

星链全解1

星链基本信息 星链卫星的寿命约为5年&#xff0c;最终目标是发射42000颗卫星。最初&#xff0c;每颗卫星重约260公斤&#xff0c;与1吨以上的大卫星相比属于“小卫星”。现在&#xff0c;向V2版进化的星链卫星重量近800公斤&#xff0c;约为老一代卫星的3倍。 点击“星链地图…

算法课程笔记——蓝桥云课第二次直播

注意是‘’ 都正确 可以理解为a的首地址也是数字&#xff0c;向右1 %p逻辑地址 Cin cout字符串“”单个字符本身‘’&#xff0c;其他时候不用加 这样就可以 逆运算 bool比较真假<从小到大排 11/25 都输出最省事 变成长度为n1的数组 考虑到整个都可能为一个颜色&#xff0c;…

Ubuntu 20.04.06 PCL C++学习记录(二十六)

[TOC]PCL中点云配准模块的学习 学习背景 参考书籍&#xff1a;《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,&#xff0c;PCL版本为1.10.0&#xff0c;CMake版本为3.16&#xff0c;可用点云下载地址 学习内容 在代码中使用ICP迭代最近点算法&#xff0c;程序随机…

人工智能论文GPT-3(3):2020.5 Language Models are Few-Shot Learners;架构;训练数据集;开源

2.1 模型与架构 我们使用了与GPT-2相同的模型和架构&#xff0c;包括其中描述的改进初始化、预归一化和可逆分词技术&#xff0c;但有所不同的是&#xff0c;我们在Transformer的各层中使用了交替的密集和局部带状稀疏注意力模式&#xff0c;类似于Sparse Transformer 。为了研…

普通人切入抖音的黄金赛道 软件自动生成文字动画视频 3天15个作品涨粉5000

文字动画&#xff0c;就是导入一段文字&#xff0c;用软件可以自动生成一条文字动画视频&#xff0c;因为这是软件自动生成的&#xff0c;所以过原创的话是很简单没什么问题的。 这种视频的特点是什么? 首先第一点就是非常简单&#xff0c;找好素材直接导入软件就可以自动生成…

LabVIEW仪器信息管理系统

LabVIEW仪器信息管理系统 在计量检测实验室的日常工作中&#xff0c;仪器检定校准是一项基础而重要的任务。随着科技的进步和实验室工作量的增加&#xff0c;传统的人工管理方式已经难以满足现代实验室对效率和准确性的要求。开发一套基于LabVIEW的仪器信息管理系统显得尤为必…

【CSAPP/计组】#1 数的存储与表示方法、机器中浮点数加减法详解

文章目录 前言一、定点格式定点整数 二、浮点数的表示方法2.1 浮点数存储2.2 浮点数加减法a. 操作数检查b. 对阶c. 尾数相加与检查溢出d. 结果规格化与溢出处理e.舍入处理 Some tips: 为什么进位/双符号判断法有效的通俗解释&#xff1f;Some tips:符号位拓展 前言 计算机中常…

【图论 单源最短路】100276. 最短路径中的边

本文时间知识点 单源最短路 图论知识汇总 LeetCode100276. 最短路径中的边 给你一个 n 个节点的无向带权图&#xff0c;节点编号为 0 到 n - 1 。图中总共有 m 条边&#xff0c;用二维数组 edges 表示&#xff0c;其中 edges[i] [ai, bi, wi] 表示节点 ai 和 bi 之间有一条…

Java 初学者必看 最全详细入门指南(一)

--------------------------------------------------------------------- 1.AIGC未来发展前景 未完持续… 1.1 人工智能相关科研重要性 拥有一篇人工智能科研论文及专利软著竞赛是保研考研留学深造以及找工作的关键门票&#xff01;&#xff01;&#xff01; 拥有一篇人工…

C++ 程序的内存分配

C 程序的内存分配 C 程序的内存分配栈堆数据区程序代码区参考 C 程序的内存分配 一个 C 编译的程序占用内存分为以下几个部分&#xff08;从高地址到低地址&#xff09;&#xff1a; 内核空间&#xff1a;由操作系统创建并控制&#xff0c;用户代码不能读写。栈&#xff1a;由…

文件系统和软硬链接

文章目录 文件系统磁盘磁盘逻辑抽象inode 软硬链接软链接硬链接 文件系统 文件分为打开的文件和没有被打开的文件&#xff0c;而只有打开的文件是在内存的&#xff0c;也就是我们之前讲的&#xff0c;然而大部分文件都不是被打开的(当前不需要被访问的)&#xff0c;它们都在磁…

arping命令详解

arping – send ARP REQUEST to a neighbour host. arping 是一个在网络中发送 ARP 请求以查找特定 IP 地址对应的 MAC 地址的命令行工具。它的功能类似于 ping 命令&#xff0c;基于ARP协议报文的交互机制&#xff0c;只能测试同一网段或子网的网络主机的连通性。 ARP 是 Add…

中国人的谦逊与生俱来

中国人的谦逊是与生俱来的&#xff0c;我们从老子的《道德经》就能探知一二&#xff1a; 一、不自夸、不自傲 《道德经》原文&#xff1a;自见者不明&#xff1b;自是者不彰&#xff1b;自伐者无功&#xff1b;自矜者不长。&#xff08;第二十四章&#xff09; 译文&#xff…