Java 内存区域划分 备忘录
最近看了《深入理解虚拟机》的内存分配与管理这部分的内容,这里做一个的总结,以加深我对知识点的理解,如有错误的地方,还望大神们指出,我及时更正;
内存区域划分
首先是下面这幅图:
图 1.0
这幅图是网上download下来的,但是它可以很直观告诉我们Java虚拟机所管理的几个内存区域(包括方法区、堆、虚拟机栈、本地方法栈、程序计数器五个区域),以及线程作用在这些内存区域时的数据访问方式(虚拟机栈、本地方法栈、程序计数器三个区域是线程独有;方法区、堆两个区域是线程间共享);
1.我们首先看看灰色模块中的 程序计数器模块;
它属于灰色模块,所以它的第一个特点就是它是线程私有的,各条线程之间的计数器互不影响,独立存储(在多线程环境下保证每条线程执行字节码指令时,指示的下一条指令不会错乱);
第二个特点是,它的用途。学过计算机组成原理的都知道PC寄存器,Java虚拟机中的这个PC寄存器功能和硬件级的PC寄存器相似,看作当前线程所执行的字节码的行号指示器(保存着下一条需要执行的字节码指令或者指令的地址),字节码解析器通过改变这个计数器的值来选取下一条需要执行的字节码指令,如条件分支(如if)、循环(如for)、跳转(如switch)、异常处理(异常表跳转地址)、线程恢复等基础功能都需要依赖这个计数器来完成;
2.再看灰色模块中的 虚拟机栈模块;
它的一个特点也是线程私有的,它的生命周期和线程相同,即一个线程执行开始,创建一个虚拟机栈,线程结束也会相应的销毁虚拟机栈;
第二个特点 虚拟机栈中的栈元素叫做栈针(如下图1.1所示),即虚拟机栈中有一个元素就表示还有一个栈针在虚拟机栈中;栈针的入栈和出栈对应着线程中对一个方法的调用到这个方法执行结束返回,当线程中的所有方法调用都执行结束,那么线程栈中的栈针也就全部出栈完成,线程执行结束,线程栈也就相应的被销毁,回收;
第三,再来看看栈针这个结构中存储的内容是什么;(如下图1.1所示),栈针中主要存有
1.局部变量表:其实这个表就是用于存储我们当前所调用的函数的参数,以及我们在函数中定义的局部变量;在Java程序被编译成Class文件时,就在方法表集合的Code属性的max_locals数据项中确定了该方法所需要分配的最大局部变量表的容量(方法表集合这部分的知识涉及到Class类文件结构中方法表集合的知识点,请自行查阅),说白了就是编译完成后,局部变量表的最大尺寸就是定了的;局部变量表的容量以变量槽(Slot)为最小单位,32位虚拟机中一个Slot可以存放一个32位以内的数据类型(boolean、byte、char、short、int、float、reference和returnAddress八种)。
2.操作数栈:Java虚拟机的解释执行引擎被称为"基于栈的执行引擎",其中所指的栈就是指-操作数栈。操作数栈也常被称为操作栈。和局部变量表一样,操作数栈也是被组织成一个以字长为单位的数组。但是和前者不同的是,它不是通过索引来访问,而是通过标准的栈操作—压栈和出栈—来访问的。比如,如果某个指令把一个值压入到操作数栈中,稍后另一个指令就可以弹出这个值来使用。虚拟机把操作数栈作为它的工作区——大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。比如,iadd指令就要从操作数栈中弹出两个整数,执行加法运算,其结果又压回到操作数栈中,看看下面的示例,它演示了虚拟机是如何把两个int类型的局部变量相加,再把结果保存到第三个局部变量的:
Java 字节码指令(可以看解释说明文字)
begin
iload_0 // push the int in local variable 0 onto the stack
iload_1 // push the int in local variable 1 onto the stack
iadd // pop two ints, add them, push result
istore_2 // pop int, store into local variable 2
end
图 1.2
在前边的字节码序列里,前两个指令iload_0和iload_1将存储在局部变量中索引为0和1的整数压入操作数栈中,其后iadd指令从操作数栈中弹出那两个整数相加,再将结果压入操作数栈。第四条指令istore_2则从操作数栈中弹出结果,并把它存储到局部变量区索引为2的位置。上图1.2 详细表述了这个过程中局部变量和操作数栈的状态变化,图中没有使用的局部变量区和操作数栈区域以空白表示。
3. 动态链接
这里先解释一下方法调用的静态解析和动态链接,静态解析是指在编译期就确定了要调用方法的具体地址,方法调用指令的符号引用参数就是直接引用;具体在Java语言中的体现为1.类的静态方法调用,类的私有方法调用,对父类的方法调用;动态链接是指,方法调用的具体地址只有在运行时才能确定;具体在Java语言中的体现为1.类的虚方法调用,典型的特征就是有override注解修饰的方法;就是,如果符号引用是在类加载阶段或者第一次使用的时候转化为直接引用,那么这种转换成为静态解析,如果是在运行期间转换为直接引用,那么这种转换就成为动态连接;动态链接用于存储运行期转换的直接引用;
4.返回地址
方法的返回分为两种情况,一种是正常退出,退出后会根据方法的定义来决定是否要传返回值给上层的调用者,一种是异常导致的方法结束,这种情况是不会传返回值给上层的调用方法.对于异常退出的情况如果这个异常没有在方法体内被catch捕获并处理,那么这个方法是不会给它的上层调用者产生任何返回值的;程序会直接跳到匹配的异常处理器的位置,第一个能够catch到这个异常的位置;
图 1.1
虚拟机栈学习体会:用了较长的篇幅介绍虚拟机栈,主要是因为这部分的内容和我们编程中的最经常使用的方法调用息息相关,理解了这些,我们在编写代码时就会有更全面和深入的考虑,写出的代码也会更健壮;
3. 接下来看图1.0中的 的第三个灰色模块 本地方法栈;
它和虚拟机栈发挥的作用非常相似,它们的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务, 而本地方法栈则为虚拟机使用到的Native方法服务;在 HotSpot虚拟机中直接就把它们合二为一;
4. 线程独占的内存区域都说完了,接下来看一看线程间共享的内存区域 绿色区域中的方法区;
它用于存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码、 等数据;
这里是一篇对方法区进行了详细介绍的博文,写的很详细;
http://blog.csdn.net/bingduanlbd/article/details/8548916/
5.绿色区域的 Java堆
Java堆随虚拟机启动时创建,它的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存;这也是GC主要管理的区域;当我们new 一个对象时,对象的数据部分就存储在堆中,该对象的引用则通常存储在栈中;
需要注意的特点是它是线程间共享访问的,所以在使用堆中的对象时,在多线程的环境下需要考虑,线程对对象的并发访问的问题;
内存泄漏和内存溢出的区别
1.内存泄漏是指我们不再使用的需要清理的对象,由于还存在引用链,这些对象仍然占用着内存,虚拟机迟迟没有进行清理,这一部分没有被正常清理的内存就是内存泄漏;
2.内存溢出是指我们真正需要使用的对象内存,超出了虚拟机能够分配给我们的内存,这时就会造成内存溢出;
Java 内存区域划分 备忘录的更多相关文章
- Java 内存区域划分
JVM的内存区域划分 学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的 ...
- Java内存区域划分和GC机制
Java 内存区域和GC机制 目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Ga ...
- 深入理解JVM - 1 - Java内存区域划分
作者:梦工厂链接:https://www.jianshu.com/p/7ebbe102c1ae来源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. Java与C++之间有一堵 ...
- Java内存区域划分、内存分配原理(转)
文章引用自 http://blog.csdn.net/OyangYujun/article/details/41173747 运行时数据区域 Java虚拟机在执行Java的过程中会把管理的内存划分为若 ...
- Java内存区域划分、内存分配原理(深入理解JVM一)
Java虚拟机在执行Java的过程中会把管理的内存划分为若干个不同的数据区域.这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,而有的区域则依赖线程的启动和结束而创建和销 ...
- 【java】JVM的内存区域划分
学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的呢? 由于Java程序是交由JVM执行 ...
- JVM的内存区域划分
JVM的内存区域划分 学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内存又是如何划分的 ...
- Java虚拟机-----------Java内存区域与内存溢出异常
Java内存区域划分 Java虚拟机运行时的数据区大致可划分为五部分:方法区,堆(两部分组成Java堆内存),虚拟机栈,本地方法栈(Java栈内存),程序计数器. 1.程序计数器 程序计数器占较小的内 ...
- JVM的内存区域划分(转)
原文链接:JVM的内存区域划分 JVM的内存区域划分 学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆.栈以及静态数据区.那么在Java语言当中,内 ...
随机推荐
- hdu2222 ac自动机入门
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- ios实现无限后台任务
需求 我们的app是使用心跳机制来保持用户的登陆状态,这样才能收到服务器发来的消息和命令,但是当app进入后台以后大约3分钟或者10分钟之后app就会被系统挂起,用户就会超时下线,这样就必须保持app ...
- 项目发布Debug和Release版的区别
一.Debug和Release的区别 Debug:调试版本,包含调试信息,所以容量比Release大很多,并且不进行任何优化(优化会使调试复杂化,因为源代码和生成的指令间关系会更复杂),便于程序员调试 ...
- zoj3953 Intervals 最大不重叠区间加强版 zoj排名第一~
Intervals Time Limit: 1 Second Memory Limit:65536 KB Special Judge Chiaki has n intervals ...
- 一步使你的asp.net网站在手机浏览器上全屏显示
首先要加入下面的代码: <meta name="viewport" content="width=device-width, initial-scale=1.0, ...
- 微信公众号第三方 推送component_verify_ticket协议
整了一天,终于弄明白了 component_verify_ticket 怎么获取的了.在此先批一下微信公众号平台,文档又没写清楚,又没有客服,想搞哪样哈! 好,回归正题. 第一,先通过开发者资质认证, ...
- 11-05-sdust-个人赛赛后随想
第二次打个人赛 这次居然打秃了,被A题卡的体无完肤.....结果之后转D题心里挂着A题...D题也被卡. 然后第二天不甘心,翘课来机房敲昨天的题,结果两题完全重新敲,都是10分钟左右敲完代码,A题1掉 ...
- Android+ESP8266+路由器实现远程控制(基于花生壳域名方式访问)
x先说一下实现的功能,其实就是远程控制 和这篇文章的控制 http://www.cnblogs.com/yangfengwu/p/5295632.html 应该说是这篇文章的升级,解决这篇文章由 ...
- 添加 hexo yilia 主题的文章阅读量
根据此篇博客(点击查看) 配置出自己的博客阅读量,里面介绍了如何配置开通 leancloud 应用 当然介绍我如何配置 yilia 显示自己的浏览量的. 首先在 yilia 主题下修改 _config ...
- Mybatis基本用法--下
Mybatis基本用法--下 第七部分 mybatis-spring-boot-starter 官网:http://www.mybatis.org/spring-boot-starter/mybati ...