JVM详解之JVM的内存区域

一、JVM是什么

1 概述

Jvm是Java Virtual Machine 的缩写,通俗来讲,JVM就是为Java程序提供运行环境的虚拟机

java文件的执行不直接在操作系统上执行,而是通过jvm虚拟机执行,所以其具有跨平台的特性

2 JVM运行流程

3 JVM的组成

3-1 类加载器

类加载器的作用是加载类文件到内存。执行一个.java程序时,通过javac命令进行编译,生成.class文件

字节码文件通过类加载器加载到内存中,通过jvm后续的模块进行加载执行程序

3-2 执行引擎

执行引擎也叫解释器,负责解释命令,提交操作系统执行

3-3 本地接口

其作用是融合不同的编程语言为java所用,一般用于与硬件有关的应用

3-4 运行时数据区

整个JVM的重点。我们所有写的程序都被加载到这里,之后才开始运行。

整个JVM框架由加载器加载文件,然后执行器在内存中处理数据,需要与异构系统交互是可以通过本地接口进行

二 JVM的内存区域

内存区域就是运行时数据区。在JVM的自动内存管理机制下,不需要为每一个对象手动释放内存,不容易出现内存泄露或溢出的问题。

1. 运行时数据区的结构

2 程序计数器

程序计数器是Java虚拟机中一块线程私有的内存区域,

作为当前线程执行字节码的行号指示器,通过改变其值来选取下一条要执行的字节码指令,支持线程恢复功能。

在JVM多线程切换时,每个线程需要有独立的程序计数器以记录各自的执行位置,互不影响。

执行Java方法时,它记录字节码指令地址,执行Native方法时,程序去计数器为空。

因为此时Java虚拟机调用的是和操作系统相关的接口,接口的实现不是Java语言,而是C语言和C++

它的生命周期随着线程的创建而创建,随着线程的结束而结束

3 Java虚拟机栈

Java虚拟机栈是每个线程私有的"内存草稿本“,专门记录Java方法是如何运行的。每个方法就像一张草稿纸(栈帧),方法开始时拿一张写,结束时扔掉。

Java虚拟机栈专门管理Java代码的执行

4 本地方法栈

专门管理外部Native(非Java)代码的执行,内部通过栈帧管理。

在HotSpot虚拟机只有“Java虚拟机栈”这一个栈,但它在处理Java方法和Native方法时会使用不同的逻辑,但内存管理机制是统一的。

5 Java堆

Java堆是JVM中最大的一块共享内存(启动时创建),专门存放对象实例和数组,也是垃圾收集器管理的主要区域。因采用分代回收算法,分为新生代和老年代,目的是优化内存回收和分配。

6 方法区

方法区是共享的内存区域,用于存储类信息,常量,静态变量,即使编译器优化后的代码等,是堆的逻辑部分

特性:内存要求宽松,垃圾回收可选且困难。

双引号字符串存于常量池中,new字符串在堆中,inter()方法返回常量池中字符串的引用

6-1 运行时常量池

运行时常量池是方法区的一部分。Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有常量池信息(用于存储编译期生成的各种字面量和符号引用)。

7 直接内存。

直接内存不属于JVM运行时数据区的一部分,但是这部分内存区域被频繁的调用,也可能发生OutMemoryError异常。

三、Java对象的创建过程

Java对象创建流程:

1. 类加载过程

虚拟机遇到一条new指令时,先检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载,解析和初始化过。如果没有,那必须先执行相应的类加载过程。

2. 分配内存

类加载检查通过后,虚拟机需要在Java堆中为对象分配内存。分配方式取决于堆内存是否规整,而规整性由垃圾收集器决定。

2-1 指针碰撞:

​ 堆内存规整时,用指针分隔已用与空闲内存,分配时只需移动指针即可

2-2 空闲列表

​ 堆内存不规整时,虚拟机维护可用内存块列表,分配时查找并更新列表

2-3 并发分配内存需解决线程安全问题

​ CAS+失败重试:通过比较和交换机制确保操作原子性,若旧值未变,则更新为新值,否则重试

​ TLAB(本地线程分配缓冲):为每个线程分配私有内存,线程在专属空间内存分配内存,减少同步开销

3. 初始化零值

内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值,这一步操作保证了对象的实例字段在java代码中可以不赋予初始值就直接使用。

4. 设置对象头

初始化零值完成之后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例,如何才能找到类的元数据信息,对象的哈希码,对象的GC分代年龄等信息。

这些信息存放在对象头中。

5. 执行init方法

上面工作都完成后,所有的字段都还为零。执行new指令后会接着执行Init方法,把对象按照程序员意愿进行初始化。

四、 对象的访问定位

建立对象就是为了使用对象,我们的Java程序通过栈上的reference数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定,目前主流的访问方式有使用句柄和直接指针两种

1. 使用句柄

如果使用句柄,那么Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息

2 直接指针

如果使用直接指针访问,那么Java堆对象的布局中就必须考虑如何防止访问类型数据的相关信息,而reference中存储的直接就是对象的地址

2-1 使用句柄访问的好处:

reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改。

2-2 使用直接指针访问的好处:

速度更快,节省了一次指针党委的时间开销。

全部评论

相关推荐

本人bg:双非本,两个实习经历,其中一个是非IT类的大厂实习。两个月前投递的众安,没动静以为挂掉了19号给我发邮件约面,约的21号晚上5点。面试岗位:保险中台后端开发(全栈)面后整体感觉:好像是被KPI了,面试官全程没开摄像头,基本是你问我答,无算法,项目一句没问纯我自己介绍,上来一句你是什么学历,给我整不会了目前现状:昨天晚上面试官下班前开面,今天早上上班秒挂,直接感谢信。果然不出所料是KPI,我真的无语了。。。面试八股我都是嘎嘎乱杀,状态非常好,就因为双非学历给我淘汰吗???众安一面(45min)自我介绍(2min)项目介绍(10min)1.Object有哪些方法2.hashcode与equals为什么要重写3.hashmap的底层自己扩展:hashmap为什么选择红黑树而不是B+树,为什么阈值是8,为什么有2的缓冲区,concurrenthashmap的底层,为什么jdk8之前用分段锁,jdk8之后cas+synchronized怎么保证线程安全的4.hashmap的扩容(直接说了concurrentHashMap的并发扩容)5.hashmap的负载因子是怎么计算的(没理解意图但是尽力在回答很多层面了,回答了两次,第一次被否定说答偏咯)6.HTTP与HTTPS的区别7.HTTPS是如何保证速度的(答的是对称加密与非对称加密的点)8.java中new一个对象的过程9.对象怎么分配的空间(第一次打错方向了之后改正成垃圾回收器的领域感觉差点意思还是没理解)自己扩展:标记清除算法10.volatile的底层原理自己扩展:CPU流水线技术 JMM内存模型 内存屏障 append-before11.mysql的隔离级别自己扩展:MVCC12.使用索引与正常查询的区别自己扩展:索引数据结构 下推索引 覆盖索引13.kafka如何解决线上一亿数据无法及时消费的问题(答的扩展服务器或限速,面试官说歪了但是跳过了,因为我简历也没写kafka)14.ai是怎样协助开发的反问环节 应聘的是啥岗位,用的啥技术栈
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务