jvm 内存模型介绍

6571b479e9f644a4a9a25a6faf8e5bed.jpg一、类加载子系统

 

1、类加载的过程:装载、链接、初始化,其中,链接又分为验证、准备和解析

装载:加载class文件

 

验证:确保字节流中包含信息符合当前虚拟机要求

 

准备:分配内存,设置初始值

 

解析:将变量从符号引用改为直接引用

 

初始化:执行类构造器方法

 

 

 

2、类加载器的分类

加载阶段使用到类加载器,类加载器分为:由C++实现的引导类加载器和由java实现的自定义加载器

 

自定义加载器又分为三层类加载器:拓展类加载器,应用程序类加载器和系统类加载器

 

 

 

①、引导类加载器:启动类加载器,将lib目录下,或-Xbootclasspasth参数指定路径存放的,java虚拟机能识别的类库加载进虚拟机;

 

②、拓展类加载器:将\lib\ext目录中,或者被java.ext.dirs系统变量所指定的路径中所有的类库加载进虚拟机;

 

③、系统类加载器:应用程序类加载器:负责加载用户类路径上所有的类库,可以直接在开发中使用这个类加载器;

 

④、自定义类加载器:用户自定义的类。

 

3、双亲委派机制

java虚拟机对class文件采用按需加载的方式,即在需要使用到类时,才加载对应的类到内存中,并且使用双亲委派机制的模式进行加载:

 

①:当一个类加载器收到了类加载的请求,不会立刻自己加载,而是将请求委托给父类的加载器去加载;

 

②、当父类加载器还存在父类加载器,则继续往上依次委托,最终的委托到最顶层的启动类加载器;

 

③、如果父类的加载器可以完成类加载器,则成功返回;如果父类加载器无法完成加载,子类加载器才会尝试着自己去加载。

 

这就是双亲委派机制的加载过程。

 

双亲委派机制的优势:

可以避免类的重复加载;

 

保护程序的安全,避免核心的api被篡改。

 

4、沙箱安全机制

java代码被限定在虚拟机特定的运行范围中,并且严格限制代码对本地资源的访问,通过这样来保护代码的的有效隔离性,防止本地系统造成破坏,这就是沙箱安全机制。

 

沙箱主要限制系统资源访问,例如:cpu、内存,文件系统、网络。不同级别的代码相对这些资源的访问的限制也可以是不一样的。

 

二、运行时数据区

1、虚拟机栈

每个线程在创建的时候,都会创建一个虚拟机栈,虚拟机栈是属于线程私有的。

 

 

 

a、栈帧(Stack Frame)

虚拟机栈中会存放着一个一个的栈帧,一个栈帧对应着一个方法,用于支持方法的调用和方法执行的数据结构;

 

虚拟机栈帧中存放着方法的局部变量表、操作数栈、动态链接和方法返回地址,在编译代码时,栈帧中需要多大的局部变量表和多深的操作数栈都已经确定好了。

 

①局部变量表:是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。注意:在mian()方法中,第一个表中的第一个位置的参数是args;

 

局部变量表存放了编译器可知的各种基本数据类型,对象引用和方法返回地址;

 

局部变量表以变量槽为最小单位,每个槽可以存放32位的长度,即long类型和doubule类型占俩个变量槽,而其他的基本数据类型占一个变量槽。

 

②操作数栈:用于保存计算过程中的中间结果,同时作为计算过程中变量的临时存放空间;

 

③动态链接:指向运行时常量池中该帧所属方法的引用;包含这个引用的目的是为了支持当前方法的代码能够实现动态链接,如:invokedynamic指令。

 

在java源文件被编译到字节文件中时,所有的变量和方法引用都作为符号引用保存在class文件的常量池里,程序运行时将其加载进方法区的运行时常量池中;

 

如描述一个方法调用了另外的其他方法时,就是  通过常量池中指向方法的符号引用来表示的,那么动态链接的作用就是为了将这些符号引用 转为调用方法的直接引用。

 

④方法返回地址:存放该方法在寄存器中的值,即是该方法的指令地址,方便执行引擎在执行完该方法后,回到该方法对应的指令行号,这样才能继续执行下去。

 

2、程序计数器

程序计数器,又称pc寄存器,存储下一条要执行的指令的地址,每个线程都有专属的pc寄存器。

 

程序执行时,会不停的切换不同的线程进行执行,有些线程可能执行一般,就被停止执行,转而执行其他线程,这时候pc寄存器会记录下知道到的指令行号,等到线程获取到资源重新执行时,会依据pc寄存器中的指令,继续往下执行。

 

3、堆

 

 

堆由新生代和老年代组成

 

新生代

新生代由Eden区(伊甸园区)和俩个Survior(幸存区),Survior0,Survior1,新生代一般用来存放新创建的对象。

 

①Endn区:几乎所有的对象都在Eden区中创建,即Eden是大部分对象产生的地方;

 

创建的对象有部分存在的周期很短,有些对象的存在周期很长,当Eden区的内存满了时,会触发Minor GC 进行垃圾收集;

 

②Survior区: 幸存区 ,幸存区划分为俩个区Survior0和Surivor1即,幸存区0和幸存区1,在进行垃圾收集时,哪个区为空则为Survior0;一般都是俩个区互相替换成为Survior0;

 

Survior0 和Survior1俩个区的存储空间一般为1:8的比例,但实际大多数情况都达不到这个比例,可以使用-XX:SurviorRatio参数进行设置。

 

老年代

老年代一般用来存放生存周期较长的对象,当老年代的存储空间不足时,会触发Major GC或Full GC进行垃圾收集。

 

新生代和老年的存储空间比例为1:2,可以通过 -XX:NewRatio 参数进行设置。

 

垃圾收集

在堆中,有三个垃圾收集算法:Minor GC、Major GC 和 Full GC

 

①Minor GC

新生代垃圾收集,只是新生代(Eden、Survior0和Survior1)的垃圾收集。

 

触发机制:当新生代中的Eden区的空间不足时触发(注意:Survior区空间不足时不会主动触发,Survior区只会被动触发机制)进行垃圾收集。因为大多数java对象都具备朝生夕灭的特性,所以Minor GC触发的非常频繁,一般回收的速度也比较快。

 

收集过程:a、新生代中,对于每个对象都有一个引用计数器,当Eden区的空间满了只有,只有还被引用的对象能存活不被清理,并且会转移到Survior0区,对象的引用计数器增加1,代表这个对象存活的年龄增大一岁;

 

b、重复a步骤,将存活的对象复制到S0区,存活年龄增大,已存在在S0区的对象也相对应的增加存活年龄;

 

c、当Eden区和S0区空间满时,会将S0中的对象转移到S1中,存活的对象相对应的存活年龄,然后Eden和S0区会被清空,存活的对象全部在S1中,并且对象的存在着不一样的存活年龄。此时S0会变成意义上的S1(区中为空),S1会变成意义上的S0;如此反复,空的区为S1,对象存活的数据区为S0。

 

d、当不断进行Minor GC知道对象的存活年达到阈值(通过-XX:MaxTenuringThreshold设置,默认是15),则达到阈值年龄的对象,会判定为生命周期较长的对象,会被promote到老年代;不断的进行Minor GC,也会不断有对象被promote到老年代中。

 

TLAB:TLAB是一块为了解决线程安全问题所设置的存储空间,属于新生代的Ede区,TLAB内存空间非常小,仅占Eden的1%,不是所有的对象的实例都能在TLAB中成功分配内存,但JVM确实是以TLAB作为分配内存的首选。

 

堆空间是所有线程共享的,但Eden中的TLAB是线程私有的,解决线程的安全问题。

 

Major GC

老年代垃圾收集,只进行老年代的垃圾收集。

一个对象如果很大,那么会直接进入老年代中,即老年代存在着大对象和存活周期长的对象。

 

触发机制:老年代的空间不足时,会尝试触发Minor GC 进行新生代的垃圾收集,如果触发后空间还是不足,则触发Major GC;

 

Major GC的速度一般会比Minor GC的速度慢10倍以上,STW的时间更长,如果触发后依旧空间不住,则报OOm错误。

 

一把只有CMS GC 会有单独收集老年代的行为,很多时候,Major GC和 Full GC都是混淆这是用触发。

 

收集过程:一般Major GC 和 Full GC 同时触发,收集整个堆。

 

Full GC

整堆收集,收集整个java堆和方法区的垃圾。

 

触发机制:a、调用System.gc()时,系统会建议执行Full GC,但不必然执行;

 

b、老年代空间不足时;

 

c、方法区空间不足时;

 

d、通过Minor GC后进入老年代的平均大小大于老年代的可用内存;

 

e、有Eden区、Survior space0(From space) 区向Survior space(To space)区复制时,对象大小大于 To space的可用空间大小,则对象复制到老年代,但对象大小又大于老年代可用空间时触发。

 

Full GC是开发或调优中尽量避免的,这样暂停的时间会短一些

 

代码优化

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

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

相关文章

【AIGC】Stable Diffusion的模型入门

下载好相关模型文件后,直接放入Stable Diffusion相关目录即可使用,Stable Diffusion 模型就是我们日常所说的大模型,下载后放入**\webui\models\Stable-diffusion**目录,界面上就会展示相应的模型选项,如下图所示。作者…

【Qt】qt常用控件之QIcon 以及 qrc机制设置图片路径(QtCreator)

文章目录 1. QIcon / windowIcon2. setIcon() 与 setwindowIcon()2.1 setIcon() 介绍与使用2.2 setWindowIcon 介绍与使用 3. 路径问题 & qrc机制的引入3.1 绝对路径 / 相对路径 的问题3.2 qrc机制3.3 在QtCreator下利用qrc机制引入图片 1. QIcon / windowIcon QIcon QIco…

C语言strlen和sizeof的区别

strlen和sizeof没有联系 前者是库函数,统计长度的标志是是否有\0 后者是操作符。计算长度的标志是字节数量。

蓝桥杯:C++排列与组合

排列是暴力枚举时的常见操作。有以下两种情况。 C的 next_permutation()是全排列函数,只能输出序列中所有元素的全排列。 本节将给出手写排列和组合的代码。因为在很多场合中不能使用系统自带的排列函数,所以需要自己编写。 全排列函数:nex…

【AIGC】Stable Diffusion的模型微调

为什么要做模型微调 模型微调可以在现有模型的基础上,让AI懂得如何更精确生成/生成特定的风格、概念、角色、姿势、对象。Stable Diffusion 模型的微调方法通常依赖于您要微调的具体任务和数据。 下面是一个通用的微调过程的概述: 准备数据集&#xf…

用EL操作JAVABEAN属性

用EL操作JAVABEAN属性 问题陈述 Smart SoftWare Inc.想要开发一款维护雇员数据(例如姓、名字、职位)的Web应用程序。该组织决定将雇员数据存储在一个JavaBean中。另外,它还希望该Web应用程序能让用户从此JavaBean中检索数据并用JSP页面和EL显示。 解决方案 要解决上述问题…

(六)【Jmeter】线程(Threads(Users))之常规线程组(Thread Group)

简介 在JMeter中,线程组是用于模拟用户并发访问的组件。线程组中的线程代表虚拟用户,线程执行的采样器模拟了用户发送请求的操作。线程组套件主要涵盖:线程组(Thread Group)、bzm-Arrivals Thread Group、bzm-Concurrency Thread Group、bzm-Free-Form Arrivals Thread G…

CISA知识点

审计流程21%;运营和业务恢复23%;保护资产27%;IT治理17%;开发12%。 领域1-信息系统审计流程 规划-现场工作-报告 (1)审计规划 了解业务使命、目标、目的和流程 找到相关规定 实施风险分析(…

爱上JVM——常见问题:JVM组成(一)

1 JVM组成 1.1 JVM由那些部分组成,运行流程是什么? 难易程度:☆☆☆ 出现频率:☆☆☆☆ JVM是什么 Java Virtual Machine Java程序的运行环境(java二进制字节码的运行环境) 好处: 一次编写&…

保育员答案怎么查找? #经验分享#微信

在大学生的学习过程中,我们经常会遇到各种难题和疑惑。有时候,我们可能会花费大量的时间和精力去寻找答案,但结果却并不尽如人意。为了帮助大家更好地解决这个问题,今天我要向大家介绍几款备受大学生欢迎的搜题软件,它…

Matplotlib plt.plot:从入门到精通,只需一篇文章!

Matplotlib plt.plot:从入门到精通,只需一篇文章! 利用Matplotlib进行数据可视化示例 🌵文章目录🌵 📊 1. 引言:为什么Matplotlib在数据可视化中如此重要?📊✨ 2. plt.pl…

[职场] 求职如何设置预期 #笔记#经验分享

求职如何设置预期 在求职的道路上,无论处于哪个年龄阶段,合理的就业期望值才能使我们的愿望与社会的需求相吻合,才能让自己在今后的工作中发挥出最大的实力与能力。 一、结合测评软件,明确求职目标 根据霍兰德职业兴趣测试结果&a…