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或者有更好的建议,随时欢迎批评指正

扫描关注

QrCode