JVM,关于JVM基础的知识,你确定不了解一下吗?

news2025/1/20 14:57:01

目录

一.JVM的概念

什么是JVM?

二.JVM的运行流程

1.class文件如何被JVM加载并运行

2.JVM运行时数据包括哪些区域(M)

三.类加载的过程(M)

四.双亲委派模型

1.双亲委派模型分析

2.JAVA中有哪些类加载器(M)

五.垃圾回收机制

1.死亡对象的标识

①引用计数算法

②可达性分析算法

 什么是GC Roots 呢?

GC Roots一般有以下几种类型:

2.垃圾回收的算法

①标记清除算法

②标记复制算法

③标记整理算法

 垃圾回收的过程?(M)

1.Minor GC(新生代的垃圾回收)

 2.Full GC(老年代的垃圾回收)

3.垃圾回收器

介绍一下垃圾回收器(M)

 主要的垃圾回收器有以下几种:


一.JVM的概念

什么是JVM?


JVM是JavaVirtualMachine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的 

二.JVM的运行流程

1.class文件如何被JVM加载并运行

①当.java文件被编译为.class文件时,.class文件会被加载到类加载子系统,然后由类加载子系统将文件加载到运行时数据区

②在运行时数据区中,类对象被加载到方法区中,便于后面new出来的实例对象可以通过这个类对象模板中创建新的对象。

③创建出来实例对象会被加载到堆中

④虚拟机栈:每个线程都会在虚拟机栈中开辟一个空间,每调用一个方法时,这个方法就会被压入栈中,也就是说每个栈中存放的是方法调用的层级

⑤本地方法栈:同样是每一个线程都会在本地方法栈中开辟一块内存,每次调用一个本地方法,这个本地方法就会被加载到本地方法栈中。

⑥程序计数器:记录当前线程所运行到的指令地址:由于考虑到java虚拟机在多线程模式下是通过线程轮流切换并分配时间片的方式进行的,因此当某个线程分配的时间片使用完但是当前线程并没有执行结束时,这时就需要使用程序计数器记录下当前线程所运行到的指令地址,当当前线程再度被分配到时间片时,从当前指令下继续执行。

2.JVM运行时数据包括哪些区域(M)

①方法区:在JDK1.7之前, 方法区又被称作永久代,在1.8及之后被称为元空间,区别在于实现方式的不同,方法区是当类对象被加载到JVM时存储的地方,类对象被存储到方法区中以便后续需要创建实例对象时直接从方法区中的类对象获取并创建实例对象。需要说明的是,方法区是所有线程所共享的

②堆:创建的实例对象都会被加载到堆空间中,堆空间的大小可以通过JVM中的参数进行设置:Xms10(最小堆内存空间) 是设置堆空间大小,Xmx10(最大堆内存空间)也是设置堆空间大小的:通常我们将这两个内存参数设置为同一个大小,我们一般将两个参数均设置为线程运行可能消耗的最大堆空间,如果内存空间比较小时,可能会出现OOM错误(OUT OF MEMORY ERROR),一旦出现这个错误,我们可以将堆空间设置的大一点。

③java虚拟机栈:每个线程都会在虚拟机栈中开辟一个空间,每调用一个方法时,这个方法就会被压入栈中,也就是说每个栈中存放的是方法调用的层级,虚拟机栈容量的大小一般由Xss这个参数确定,如果栈溢出,会报出StackOverFlow错误

④本地方法栈:同样是每一个线程都会在本地方法栈中开辟一块内存,每次调用一个本地方法,这个本地方法就会被加载到本地方法栈中。

⑤程序计数器:记录当前线程所运行到的指令地址:由于考虑到java虚拟机在多线程模式下是通过线程轮流切换并分配时间片的方式进行的,因此当某个线程分配的时间片使用完但是当前线程并没有执行结束时,这时就需要使用程序计数器记录下当前线程所运行到的指令地址,当当前线程再度被分配到时间片时,从当前指令下继续执行。

三.类加载的过程(M)

1.加载

将所有的.class文件全部加载到虚拟机中

2.验证

根据.class文件的规范对当前的文件进行验证

3.准备

将各种类型的值初始化为默认的值,int 初始化为0,float初始化为0.0f.......

4.解析

将java虚拟机中常量池的符号引用替换为直接引用,也就是初始化常量池的过程。(例如:原本常量池中的字符串并没有直接引用,(还是占位符),在这个过程中将创建一个新的字符串并将常量池中的占位符进行替换)

 

5. 初始化

之前的工作都是准备工作,这一步是真正执行类中的java代码,经过这一步,真正的java对象才会被创建出来

四.双亲委派模型

1.双亲委派模型分析

不同的类在加载时会使用不同的类加载器:

 其类加载器的策略如下:当创建一个类时,先从applicationClassLoader开始向上转发,一直到BootStrapClassLoader,BootStrapClassLoader在自己的加载路径中查找是否存在这个类,有则加载,没有则向下转发到ExtClassLoader,ExtClassLoader在自己的加载路径中查找有没有这个类,有则加载,没有则向下转发到ApplicationClassLoader,在自己的路径中查找并加载这个类

2.JAVA中有哪些类加载器(M)

五.垃圾回收机制

1.死亡对象的标识

①引用计数算法

概念:当对象被引用,那么其引用的次数就加1,当引用的对象为0的时候,就将这个对象标识为死亡对象,这个对象就该被回收了。

图示如下:

 过程分析:当创建两个对象,定义两个变量指向创建的两个对象,此时这两个对象的引用都+1,同时使用对象的instance属性也指向这两个创建的对象,这时这两个新创建的对象的引用次数都是2了,但是如果对这两个变量置为空,则两个新创建的对象的引用次数-1,但是由于两个变量都为空了,两个变量的instance属性也无法访问到这两个对象了,但是由于这两个对象的引用次数并没有变为0(instance属性仍然指向两个对象),因此这两个对象无法进行回收,这也就造成了内存泄漏的问题

notes:内存泄漏:内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

内存泄漏问题在程序刚开始运行时并不容易发现,当程序运行了一段时间,堆空间不断放入新的对象而无法及时清除,最终会导致堆空间被占满,导致程序崩溃。

②可达性分析算法

可达性分析算法的实现原理如下:从GC Roots(起始结点集)根据引用关系从上往下搜寻,搜寻的路径称为【引用链】,如果某个结果到任何一个根对象都没有引用链,则称这个对象不可达,标识这个对象不可达。


在垃圾回收时首先会搜寻到所有的根结点【枚举根结点】,然后从这些根结点从上向下搜寻,这个过程需要暂停用户线程,即触发STW,能搜寻到说明这个对象保留,如果不能搜寻这个对象则使用垃圾回收的算法对其进行回收。

 什么是GC Roots 呢?

GC Roots也是对象,而且是JVM一定不能回收的对象,在JVM进行GC的时候,在所有用户到达safepoint之后首先会进行STW,暂停所有用户的线程,之后进行对根结点的枚举,之后再从根结点从上往下搜寻。

GC Roots一般有以下几种类型:

1、方法区静态属性引用的对象
全局对象的一种,Class对象本身很难被回收,回收的条件非常苛刻,只要Class对象不被回收,静态成员就不能被回收。

2、方法区常量池引用的对象
也属于全局对象,例如字符串常量池,常量本身初始化后不会再改变,因此作为GC Roots也是合理的。

3、方法栈中栈帧本地变量表引用的对象
属于执行上下文中的对象,线程在执行方法时,会将方法打包成一个栈帧入栈执行,方法里用到的局部变量会存放到栈帧的本地变量表中。只要方法还在运行,还没出栈,就意味这本地变量表的对象还会被访问,GC就不应该回收,所以这一类对象也可作为GC Roots。

4、JNI本地方法栈中引用的对象
和上一条本质相同,无非是一个是Java方法栈中的变量引用,一个是native方法(C、C++)方法栈中的变量引用。

5、被同步锁持有的对象
被synchronized锁住的对象也是绝对不能回收的,当前有线程持有对象锁呢,GC如果回收了对象,锁就失效了。

2.垃圾回收的算法

①标记清除算法

算法思路:标记当前所有对象中的不可用对象,在原位将其进行标注,之后进行清除

缺陷:但是这个算法的缺陷也比较明显:在原位将不可用对象进行了清除,会产生大量不连续的可用空间碎片,如果在这时需要创建较大的对象但是当前连续的可用空间不满足时,则需要触发下一次垃圾回收。

 

②标记复制算法

算法思路:将全部的可用空间划分为两部分,比如划分为空间1和空间2,空间1在清除完不可用对象后,存在大量的不连续的可用空间的碎片,空间2对空间1中的可用和不可用对象进行分类整理排列,在排序完成后将空间1进行整体清除,后面再次清除时重复这种操作

缺陷:这种算法的缺陷也相对明显,再每一次垃圾回收的过程中,只有一半的空间能真正发挥作用

③标记整理算法

算法思路如下:在每次清除完部分的不可用对象之后就对全部的对象进行排序整理

缺陷:每次清除都要进行排序整理,算法效率相对较低

 垃圾回收的过程?(M)

 不同的类对象进行了分代处理,将所有的类对象分为了新生代和老年代,其中新生代占堆空间的1/3,老年代占堆空间的2/3,新生代的空间中还有1/5的survivor(幸存者分为from和to两个区域)区域。对象进行了分代处理,垃圾回收也被划分为两种类型:①Minor GC(新生代的垃圾回收)②Full GC(Major GC/Full GC 发生在老年代的垃圾回收)。

1.Minor GC(新生代的垃圾回收)

新生代的垃圾回收采用的是复制算法(因为新生代中的对象迭代比较频繁,所以需要效率相对较高的算法,虽然复制算法所消耗的空间较大,但是其效率相对较高),其过程如下:


①创建对象时在Eden区直接创建,此时survivor两块区域都为空(空间大小之比:Eden:from:to=8:1:1)

②当我们再次创建对象,发现Eden区当前的容量不足以存放当前对象,则将Eden区的对象进行判断处理,对判定死亡的对象进行清除,存活的对象将其移至survivor区中的from区,移动到from区的对象的“年龄”+1;

③Eden区持续创建新的对象,并对没有引用的对象进行清除之后,Eden区存活的对象都被移动到了from区,Eden区和from区都被占用满了,这时要把from区的对象移动到to区,然后将Eden区和from区都进行清空,在上一轮中被放置在from区的对象的年龄再加1

⑤在下一轮GC中会将from区和to区的位置互换,此时to区为空,from区和Eden区继续参与下一轮的GC ,重复上面的步骤

⑥经过不断的GC,在新生代中的对象的年龄达到了一定的阈值(默认阈值是15),这时候就要将这些对象移动到老年代

 总结:我们纵观整个新生代垃圾处理的过程来看:在每一轮的GC中,新的对象会在Eden区创建,当Eden区剩余的容量不足以创建新的对象时,将所有的Eden区存活的对象移动到from区,在下一轮GC时会将from和Eden区存活的对象全部复制到to区,将from区和Eden区全部清空,将to区和from进行调换继续进行垃圾回收。

 2.Full GC(老年代的垃圾回收)

老年代的垃圾回收策略并不是采用复制算法,而是标记整理算法, 因为进入老年代的对象相对于新生代而言并不会进行频繁的创建和销毁,所以使用标记整理算法比较适合。Full GC相对于Minor GC要慢很多,所以在JVM调优过程中,很大的一部分工作都是对Full GC的调节

3.垃圾回收器

介绍一下垃圾回收器(M)

在讲述垃圾回收器之前,我们先说一下垃圾回收器的发展过程:由于在垃圾回收的过程中要执行STW,所有的用户线程在这个过程中都要暂停线程服务,所以缩短STW的时间是垃圾回收器在完成业务需求之后所要追求的目标.。在刚开始时使用单线程垃圾回收器,随着程序规模的不断扩大和程序内容的不断丰富,单线程垃圾回收器无法满足用户需求,多线程垃圾回收器应运而生,随着程序的不断发展,多线程STW的时间也越来越长,又开始尝试新的垃圾回收器来缩短STW的时间

 主要的垃圾回收器有以下几种:

  • Serial收集器(复制算法)
    新生代单线程收集器,标记和清理都是单线程,优点是简单高效。是client级别默认的GC方式,可以通过-XX:+UseSerialGC来强制指定。
  • Serial Old收集器(标记-整理算法)
    老年代单线程收集器,Serial收集器的老年代版本。
  • ParNew收集器(停止-复制算法) 
    新生代收集器,可以认为是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现。
  • Parallel Scavenge收集器(停止-复制算法)
    并行收集器,追求高吞吐量,高效利用CPU。吞吐量一般为99%, 吞吐量= 用户线程时间/(用户线程时间+GC线程时间)。适合后台应用等对交互相应要求不高的场景。是server级别默认采用的GC方式,可用-XX:+UseParallelGC来强制指定,用-XX:ParallelGCThreads=4来指定线程数。
  • Parallel Old收集器(停止-复制算法)
    Parallel Scavenge收集器的老年代版本,并行收集器,吞吐量优先。
  • CMS(Concurrent Mark Sweep)收集器(标记-清理算法)
    高并发、低停顿,追求最短GC回收停顿时间,cpu占用比较高,响应时间快,停顿时间短,多核cpu 追求高响应时间的选择。

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

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

相关文章

Maven私服搭建

为什么要搭建私服 通常在maven项目的pom.xml文件中引入了某个依赖包之后&#xff0c;maven首先会去本地仓库去搜索&#xff0c;本地仓库搜索不到会去maven的配置文件settings.xml中配置的maven镜像地址去找&#xff0c;比如&#xff1a; <mirrors><!-- mirror| Specif…

动态规划 --- 电线布设

动态规划 — 电线布设 题目描述 说是话&#xff0c;刚看到也是很懵逼&#xff0c;不想交子集是什么&#xff1f;乱七八糟的连线。 其实仔细想想后&#xff0c;觉得题目应该是说给定了这些点的连接端点&#xff0c;然后从他给的连线中选择出不想交的且条数最多的连线&#x…

Flink自定义函数之标量函数(UDF函数)

1.背景 flink本身给我们提供了大量的内置函数&#xff0c;已经能满足我们绝大部分的需求&#xff0c;但是如果确实是碰到了一些特殊的场景&#xff0c;无法满足我们的需求的时候&#xff0c;我们可以使用自定义函数来解决。 自定义函数大致可以分为标量函数&#xff08;UDF函…

Linux-安装Python2.7

一、简介 正常情况下&#xff0c;使用sudo apt install python来安装就好了。如果发现这个指令报错了&#xff0c;此时就需要手动安装Python2.7了。例如报错如下&#xff1a; 二、实操 1.下载Python2.7的相关源码&#xff08;以2.7.18为例&#xff09; 下载地址如下&#xff1a…

Linux第四章

文章目录 前言一、快捷键小技巧二、软件安装三、systemctl控制软件启动关闭四、软链接五、日期和时区六、ip地址和主机名七、配置linux固定ip地址八、网络请求和下载九、端口十、进程管理十一、主机状态监控十二、环境变量十三、linux文件的上传和下载十四、压缩和解压总结 前言…

第五章 使用RAID与LVM磁盘阵列技术

第五章 使用RAID与LVM磁盘阵列技术 一、RAID磁盘冗余阵列 1、部署磁盘阵列 &#xff08;1&#xff09;、RAID0、1、5、10方案技术对比 RAID级别最少硬盘可用容量读写性能安全性特点02nn低追求最大容量和速度&#xff0c;任何一块盘损坏&#xff0c;数据全部异常。12n/2n高追…

魔兽世界服务端用户注册以及网页的搭建教程

魔兽世界服务端用户注册以及网页的搭建教程 大家好我是艾西&#xff0c;上一章我们讲解了怎么编译一个魔兽的服务端以及安装最后进到我们自己的游戏。那么在平时娱乐的同时肯定是需要和朋友们一起玩游戏才会更有意思&#xff0c;那么今天艾西教大家怎么搭建用户注册页面以及网…

java进程引发的内存泄露问题排查分析

近期工作过程中遇到了一次容器内存不断增高&#xff0c;最终达到90%引发告警的情况。 特征1&#xff0c;把监控面板时间轴拉长会发现&#xff0c;重启后内存占用78%左右&#xff0c;每天增长1%&#xff0c;大约2周后会涨到90%触发告警&#xff08;即如果2周内有代码发布部署&am…

2022-04-27:用go语言重写ffmpeg的remuxing.c示例。

2022-04-27&#xff1a;用go语言重写ffmpeg的remuxing.c示例。 答案2022-04-27&#xff1a; ffmpeg的remuxing.c是一个用于将多媒体文件从一种容器格式转换为另一种容器格式的命令行工具。它可以将音频、视频和字幕等元素从源文件中提取出来&#xff0c;并按照用户指定的方式…

构造函数和析构函数

1.构造函数 1.1 .构造函数概括 、构造函数是一个特殊的成员函数&#xff0c;名字与类名相同,创建类类型对象时由编译器自动调用&#xff0c;以保证每个数据成员都有 一个合适的初始值&#xff0c;并且在对象整个生命周期内只调用一次。 构造函数是特殊的成员函数&#xff0c…

简单认识 Postman界面操作

查看本文前 您需要先登录Postman 如果还没有处理好 可以先查看我的文章 Postman登录注册指导 右上角的 Home 代表主页 就是我们现在看到的这个界面 Workspaces 是一个工作空间管理 这里 我们选择进入 我的工作空间 之后 我们所有的接口请求 就都是在这一块完成的 Collection…

ubuntu中安装VMware Tools,实现Windows文件拖入Ubuntu

ubantu作为一款非常好用的Linux发行版本&#xff0c;深受广大开发者的喜爱&#x1f603;&#xff0c;为了开发的方便&#xff0c;人们常常在windows电脑中安装VMware虚拟机来运行Linux系统&#xff0c;我们时常会遇到这样一种情况&#xff1a;无法互传虚拟机与主机文件。 原因就…

终端连接工具Tabby的下载、安装与配置

目录 一、终端连接工具Tabby的下载1.1、Tabby的下载地址1.2、Tabby的下载步骤 二、终端连接工具Tabby的安装三、终端连接工具Tabby的SSH连接四、终端连接工具Tabby的SFTP 传输工具4.1、服务器上的文件传输到本地电脑4.2、本地电脑的文件传输到服务器 五、终端连接工具Tabby的设…

基于网络爬虫和SpringBoot框架的晋江文学小说小型网站项目

一、Python网路爬虫技术的设计与实现 Scrapy是一个为了爬取网站数据&#xff0c;提取结构性数据而编写的应用框架&#xff0c;常可以应用在包括数据挖掘&#xff0c;信息处理或存储历史数据等一系列的程序中。项目中&#xff0c;主要采取Scrapy框架实现一个爬虫&#xff0c;抓…

JavaSE3(4/26)

目录 1.线程的状态 2.线程安全问题 3.synchronized的具体用法 4. 1.线程的状态 首先明白进程的状态:就绪或者阻塞 上述说的就绪和阻塞其实是针对系统中的线程状态(PCB) Java中对于Thread类中的线程的状态进行了进一步的细化 NEW: Thread对象有了,但是线程还没有被执行 TERMI…

RabbitMQ之介绍以及安装

1.1 MQ的相关概念 1.1.1 什么是MQ ​ MQ&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO先入先出&#xff0c;只不过队列中存放的内容是message而已&#xff0c;还是一种跨进程的通信机制&#xff0c;用于上下游传递消息。在互联网架构中&#xff0c;MQ…

摄影tips

一、基础知识 相机挡位 A档就是全自动模式或称场景智能自动模式&#xff0c;该拍摄模式下&#xff0c;相机会根据光线和你所拍摄的对象等场景环境自行设置快门、光圈等参数&#xff0c;你不需要调整任何参数&#xff0c;拿起相机对焦按快门就行&#xff0c;也就是AUTO模式。虽…

opengauss编译和使用oracle_fdw

opengauss虽然继承自postgresql9.2&#xff0c;但由于做了魔改&#xff0c;网上通用的从oracle_fdw源码编译安装到postgresql的方法&#xff0c;是否成功的应用到opengauss&#xff0c;并不一定&#xff0c;今天试了一下&#xff0c;参照opengauss官网文档&#xff08;其实写的…

Spring Bean的作用域及生命周期

目录 前言&#xff1a; Bean的作用域&#xff08;Scope&#xff09; 单例模式 原型模式&#xff08;多例作用域&#xff09; 请求作用域&#xff08;request&#xff09; 会话作用域 全局作用域 网络长连接 Spring执行流程 Bean的生命周期 测试 小结&#xff1a; 前…

多模态论文串讲:ALBEF VLMo BLIP CoCa Beit V3

文章目录 前言ALBEF:Align before Fuse: Vision and Language Representation Learning with Momentum Distillation(2021-10)VLMO: Unified Vision-Language Pre-Training with Mixture-of-Modality-Experts(2021-11)relatedmethod BLIP&#xff1a;Bootstrapping Language-Im…