JVM学习之内存结构
java运行时对象创建在什么地方?堆和栈空间又有什么区别?听闻已久的Young,Old区又是什么鬼?听说有个常量池,这个又是啥
要想在脑海中清晰的布局一个java类在加载到使用的过程中,整个类生命周期中,各项数据究竟最终落在哪个板块上,就需要了解下JVM的内存区域了
I. 内存布局
简单来讲,内存可以划分为三块:
- 堆
- 最大的一块区域,创建的对象都在这个上面
- 方法区
- 加载类时对应的类信息,常量,静态变量
- 栈
- 虚拟机栈和本地方法栈,存储线程相关的信息
II. 分区详解
1. 堆区
所有线程共享,虚拟机启动时创建,存放对象实例
垃圾回收,主要就是针对堆区而言,一般划分为年轻代,年老代
- Young区:Edge + From Survivor + To Sruvivor (8:1:1)
- Old区
对象开始在Young区,一般内存回收时,会有标记整理,就涉及到两个Survivor区的转移,对象存的时间够久之后,就会将对象塞入Old区
2. 方法区
所有线程共享,存储JVM加载的类信息,常量,静态变量,即使编译代码
3. 程序计数器
当前线程所执行的字节码的行号指示器,线程私有
字节码解释器,就是来改变这个计数器来选择下一条要执行的命令
4. Java虚拟机栈
线程私有,描述java方法执行的内存模型,它的生命周期与线程相同
虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
- 局部变量表(所占用空间,编译期间分配完成)
- 编译期可知的各种基本数据类型
- 对象引用
- returnAddress类型(指向了一条字节码指令的地址)
- 操作栈
- 动态链接
- 方法出口
当栈深大于允许的高度时,会抛出StackOverflowError,常见于递归调用异常的情况
当无法申请到足够的空间时,会抛出OutOfMemoryError
5. 本地方法栈
本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务
III. 其他
参考:
- JVM内存结构
- 《深入理解Java虚拟机-JVM高级特性与最佳实践》
个人博客: Z+|blog
基于hexo + github pages搭建的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
声明
尽信书则不如,已上内容,纯属一家之言,因本人能力一般,见识有限,如发现bug或者有更好的建议,随时欢迎批评指正
- 微博地址: 小灰灰Blog
- QQ: 一灰灰/3302797840