JVM内存模型小结
JVM运行时的数据区域划分图如下,该图是JVM内存模型最主要的内容。
从图中可以看出来,JVM将内存主要划分为五个部分:程序计数器、Java虚拟机栈、本地方法栈、Java堆和方法区。这些被划分为用途不一的数据区域有着各自的特点,它们都有自己创建和销毁的时间,有的区域随着进程的启动而存在,有的是伴随着用户线程的启动而建立、随着线程的结束而销毁。

(一) 程序计数器(Program Counter Register)
1> 内存空间较小;
2> 当前线程所执行的字节码行号指示器;
功能:a、在JVM中,字节码解释器的工作进行就是通过改变计数器的值来选取下一条需要执行的字节码指令
b、在3>中有解释,是作为线程切换回来继续执行的标记点
3> 线程私有;
线程私有:通俗来讲就是每一个线程在执行时都有一个独立的程序计数器,各个线程被独立存储。目的是为了记录所执行的线程进行到了哪一步。这样设计的原因主要是由多线程的实现方式所决定的,在Java虚拟机中,多线程的实现是通过线程轮流切换并分配处理器执行时间的方式,也就是在任何一个具体的时刻下,一个处理器只能够执行一个线程下的代码指令,这样在不断的线程切换过程中,同一个线程想要继续往下执行,就必须知道它上一次执行的位置,这个工作就是通过程序计数器完成的。
4> 计数器的值;
若线程正在执行的是Java方法:正在执行的虚拟机字节码指令的地址;
若线程正在执行的是Native方法:空值(Undefined);
Native方法(本地方法):为了补充Java语言无法直接访问系统底层的一种方法,由C或C++语言完成,实际上Native Method就是Java调用非Java代码的接口。
5> 计数器这块内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
6> 生命周期与线程相同。
(二)Java虚拟机栈(Java Stack)
1> 定义:描述Java方法执行的内存模型;
a、详细解释:每个方法执行时都会创建一个栈帧,在这个栈帧中存放着“局部变量表、操作数栈、动态链接、方法出口等”。
以我的理解就是这一块内存就是一个栈,栈帧是Java虚拟机栈的诸多元素,每一个栈帧都代表这一个方法正在被执行,其中存放着一些有关该方法中信息。
每一个方法从调用一直到执行结束,也就对应着一个栈帧在Java虚拟机栈中入栈出栈的过程。
b、局部变量表:
基本数据类型、(64位的long和double类型的数据会占用2个局部变量空间,其余占1个)
对象引用、(reference类型??,不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能 是指向一个代表对象的句柄或其他与此对象相关的位置)
returnAddress类型 、(指向了一条字节码指令的地址)
局部变量表所需的内存空间在编译期间完成分配,所以在线程进行时调用了一个方法,为之创建的栈帧中局部变量空间是完全确定的,并且在方法执行过程中不会改变局部变量表的大小。
2> 线程私有;
线程私有: 也就是和计数器一样,每一个线程有独立的Java虚拟机栈,这个线程中的每个方法执行过程就会创建一个栈帧,方法执行的全过程就是栈帧在该线程对应的虚拟机栈中入栈和出栈的过程。
3> 生命周期与线程相同;
4> 该内存区域两种异常状况:
a、线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;
b、若虚拟机支持动态扩展,如果扩展时无法申请到做够的内存,就会抛出OutOfMemoryError异常。
StackOverFlowError表示当前线程申请的栈超过了事先定好的栈的最大深度,但内存空间可能还有很多。
而OutOfMemoryError是指当线程申请栈时发现栈已经满了,而且内存也全都用光了。
5> 不能简单地将Java内存区简单分为堆和栈。
这样区分太过粗糙,只不过是将对象和局部变量区分开,简单地认为对象存放在堆中,局部变量存放在栈中。其实从上面的整理中也可以看出来,Java虚拟机栈实际上是由这些栈帧组成的,而每个栈帧中的内容并不只有局部变量表。
(三)本地方法栈
1> 定义:与Java虚拟机栈的定义很相似,可以说是Native方法执行的内存模型;
2> 虚拟机规范中对本地方法栈中方法使用的语言、使用方式与数据结构并没有强制规定。甚至有的虚拟机(Sun HotSpot)直接就把本地方法栈和虚拟机栈合二为一;
3> 抛出StackOverflowError和OutOfMemoryError异常的情况与Java虚拟机栈是一样的;
4> 其他特性参考Java虚拟机栈。
(四)Java堆
1> 系Java虚拟机所管理内存中最大的一块,虚拟机启动时创建;
2> 被所有线程共享;
所有地线程都可以访问不同地对象,从内存分配地角度来看,线程共享地Java堆中可能划分出多个线程私有地分配缓冲区(TLAB),不过无论如何划分,无论哪个区域,存放地都是对象实例,这样不同地线程将各自地对象实例放在了看似共享的Java堆的各自的缓冲区上,这样的好处是可以更好的回收内存,也可以更快分配内存。
3> 唯一目的就是存放对象实例,几乎所有实例对象都存在此处;
在Java虚拟机规范中描述为:所有的对象实例以及数组都要在这里分配内存。但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所以这里会严谨地加上“几乎所有”而不是全部,至于什么是逃逸分析,栈上分配,标量替换,以后学习中应该会专门去了解学习一下吧。
4>可以处于物理上不连续的内存空间,但逻辑上需要连续;
5> 可以实现固定大小的,也可以是可扩展的。若在堆中没有内存完成实例分配,并且堆也无法再扩展时,将抛出OutOfMemoryError异常;
6> 又称“GC堆'(Garbage Cpllected Heap)
内存回收用到的终极算法:分代收集算法,今后可以专门学习一下,该算法也是多个算法的整合。
(五) 方法区(Method Area)
1> 与Java堆类似,各线程共享的内存区域;
2> 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等;
3> 规范中描述为堆的一个逻辑部分,习惯称为Non-Heap(非堆),目的是为了与Java堆区分;
4> 被称作“永久代”;
本质上两者并不一样,这样的叫法是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已,这样GC收集器就能像管理Java堆一样管理这部分内存,省去专门为方法区编写内存管理代码的工作。当然方法区也可以不进行GC收集。
5> 不需要连续的内存和可以选择固定大小或者可扩展外,也可以不实现GC收集;
该区域的内存回收目标主要是针对常量池的回收和对类型的卸载,但效果不好,条件苛刻,但是对于这部分的回收确实是有必要的。
6> 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常
(六) 运行时常量池
1> 方法区的一部分;
Class文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译时生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
2> 受到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常;
(七) 直接内存
1> 不属于虚拟机运行时数据区的一部分,也不是规范中的定义;
2> JDK1.4加入了NIO类,一种基于通道与缓冲区的新I/O方式,NIO可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为直接内存的引用来操作直接内存,这样可以避免在Java堆和Native堆来回复制数据,从而提高性能;
3> 受总内存影响,也会出现OutOfMemoryError异常。
以上总结的就是JVM内存模型的相关概念和知识点,前五项以及那张内存模型图需要牢记,其中有些许疑问,不过也都是某些概念上的问题,具体关于每一块内存区域的定义作用,抛出的异常类型,已经理解。
————————————————
版权声明:本文为CSDN博主「Adelaide_Guo」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Adelaide_Guo/article/details/75394973
JVM内存模型小结的更多相关文章
- JVM内存模型和结构详解(五大模型图解)
JVM内存模型和Java内存模型都是面试的热点问题,名字看感觉都差不多,实际上他们之间差别还是挺大的. 通俗点说,JVM内存结构是与JVM的内部存储结构相关,而Java内存模型是与多线程编程相关@mi ...
- JVM内存模型 小小结
可以看一下我的另一篇总结 JVM运行时数据区与JVM堆内存模型小结 推荐一篇文章,尚学堂的 Java内存模型深度解读 . 不方便全文转载,就摘录下吧. 以往的认知都是以基本类型.引用类型.常量.方法等 ...
- JVM运行时数据区与JVM堆内存模型小结
前提 JVM运行时数据区和JVM内存模型是两回事,JVM内存模型指的是JVM堆内存模型. 那JVM运行时数据区又是什么? 它包括:程序计数器.虚拟机栈.本地方法栈.方法区.堆. 来看看它们都是干嘛的 ...
- Java基础知识强化100:JVM 内存模型
一. JVM内存模型总体架构图: 方法区和堆由所有线程共享,其他区域都是线程私有的 二. JVM内存模型的结构分析: 1. 类装载器(classLoader) 类装载器,它是在java虚拟机中用途是 ...
- JVM内存模型、指令重排、内存屏障概念解析
在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...
- JVM内存模型和性能优化 转
JVM内存模型和性能优化 JVM内存模型优点 内置基于内存的并发模型: 多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于 ...
- JVM内存模型和性能优化
JVM内存模型优点 内置基于内存的并发模型: 多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于数据库锁. 多核并行计算模 ...
- JVM初探 -JVM内存模型
JVM初探 -JVM内存模型 标签 : JVM JVM是每个Java开发每天都会接触到的东西, 其相关知识也应该是每个人都要深入了解的. 但接触了很多人发现: 或了解片面或知识体系陈旧. 因此最近抽时 ...
- JVM内存模型和关键参数设置
一. JVM内存模型: Jvm内存模型是学好Java很重要的一部分,该部分学习能让我们在系统运维的时候,或者优化服务器的时候能够有方法,懂原理. 二. Jvm关键参数: 1. 堆大小设置参数: -Xm ...
随机推荐
- 【Kotlin】初识Kotlin之面向对象
[Kotlin]初识Kotlin之面向对象 1.类 在Kotlin中,类用关键字class来定义 如果一个类具有类体,那么需要使用{ }来写类体内容,如果不需要类体,那么只需要定义类名就可以了 // ...
- 『无为则无心』Python面向对象 — 57、类属性和实例属性
目录 1.类属性 (1)类属性的访问 (2)修改类属性 2.类属性和实例属性区别 1.类属性 (1)类属性的访问 类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有. 类属性可以使用 ...
- [题解]RQNOJ PID86 智捅马蜂窝
链接:http://www.rqnoj.cn/problem/86 思路:单源点最短路 建图:首先根据父子关系连双向边,边权是距离/速度:再根据跳跃关系连单向边,边权是自由落体的时间(注意自由下落是一 ...
- 李宏毅机器学习笔记——新手感悟——PM2.5作业
python也不会,计算机也不会,啥都不会,只带了个脑子考了计算机研究生.研究生选了人工智能方向.看来注定是漫长的学习之旅. PM2.5作业,我是一个字都看不懂.所以我采用了直接看答案的方案.把答案看 ...
- Excel数据可视化图表设计需要注意的几个问题
大数据发展迅速的时代,数据分析驱动商业决策.对于庞大.无序.复杂的数据要是没经过合适的处理,价值就无法体现. 可以想象一本没有图片的教科书.没有图表.图形或是带有箭头和标签的插图或流程图,那么这门学 ...
- 关于WinForm布局那些事情
最近项目中,需要用WinForm做一些简单的功能,给第三方作为测试用.本来想着简单的拖几个控件,布局一下就了事了的.但是因为第三方是个大客户,需要展示出我们的技术水平.遂好好的研究了一下WinForm ...
- appium ios 相对坐标点击和控件滑动操作
环境: 系统:ios 10.13.6 (17G12034) appium:1.14.0 xcode:10.1 iphone:iphone7 12.4 在尝试使用driver.tap([(a,b)],5 ...
- JAVA ArrayList集合底层源码分析
目录 ArrayList集合 一.ArrayList的注意事项 二. ArrayList 的底层操作机制源码分析(重点,难点.) 1.JDK8.0 2.JDK11.0 ArrayList集合 一.Ar ...
- LeetCode-095-不同的二叉搜索树 II
不同的二叉搜索树 II 题目描述:给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 .可以按 任意顺序 返回答案. 二叉搜索树(Binary ...
- 超强视频超分AI算法,从此只看高清视频
最近发现一个特别强的视频超分算法----BasicVSR,在真实世界数据集中,实现了前所未有的视觉重建效果,最近它还拿下了超分比赛NTIRE 2021三冠一亚的优异成绩,登上了CVPR 2022. 视 ...