JVM(1)——运行时内存结构

读《深入Java虚拟机》的时候,第一章就是描述JVM在内存上的结构模型,特此记录整理。(图暂时借一下YSOcean的,稍后用自己画的替换)。

JVM运行时内存结构(内存结构模型)

java虚拟机规范定义的运行时数据区:
在这里插入图片描述

  • 堆:最大的的一块是堆,属于线程公有的区域,用来存放对象实例。
  • 栈:分为本地方法栈,以及虚拟机栈,是线程私有的,分别用于调用native方法和java方法。每次调用方法的时候,栈顶会创建一个栈帧,存放局部变量表、操作数栈、动态链接、方法返回地址。
  • 程序计数器:用来存储当前执行的指令地址,是线程私有的。(唯一一个不会抛OOM的区域)
  • 方法区:线程共享区域,存放类的结构信息、常量、静态变量、运行时常量池(存放编译期产生的字面量和符号引用)。

Hotspot JDK1.8的运行时数据区:

hotspot运行时数据区
在这里插入图片描述
与JVM对于运行时内存结构模型的规范相比,Hotspot的具体实现还是有一些差别的,主要是以下三点:

①、将Java虚拟机栈和本地方法栈合二为一;

②、元数据区取代了方法区,并且元数据区不在Java虚拟机中,而是在本地内存中。

③、运行时常量池由方法区中移到了堆中

垃圾回收与异常

  • StackOverFlow:如果线程申请的栈深度大于虚拟机所允许的最大深度,会报StackOverFlow。说白了就是某个线程里的栈深度过深(递归深度过深,比如没有终止条件的无限递归)就会报StackOverFlow,这里的最大深度是由参数xss控制的。

  • OutOfMemory:如果虚拟机在拓展栈的时候无法申请到足够的内存空间,会报OutOfMemory。不止是栈,堆里也会发生OOM,说白了就是JVM的物理内存不够用了。刚才的StackOverFlow是针对任何一个线程而言的,因为最大栈深度是对每个线程的限制;OOM则是针对虚拟机整体而言的。一般来说,开启过多线程会引起OOM。

  • StackOverFlow和OOM的关系:为了解决StackOverFlow,可以把每个线程的空间设置的大一些;但如果这么做了,同样的JVM空间,可供开启的线程数就少了,更易造成OOM。

Java堆

  • 线程共享,存放对象实例和数组(随着JIT的发展和逃逸分析技术的成熟,有的对象会分配在栈上);
  • 垃圾收集:java堆可以进一步分为新生代和老年代,而新生代又可以分为Eden空间、From Survivor空间、To survivor空间,主要是因为新生代使用的是复制算法。
  • 根据Java虚拟机规范,Java堆可以处于物理上不连续的内存空间中, 只要逻辑上连续即可,实现时既可以实现成固定大小,也可以是扩展的。如果堆中没有完成实例分配,并且无法扩展,将抛出OOM异常。

方法区

存储已经被JVM加载的类的信息、常量、静态变量、即时编译器编译后的代码等数据。运行时常量池用来存放编译期生成的各种字面量和符号引用。

方法区也称为永久代,因为垃圾回收期对方法区的垃圾回收较少,主要是针对常量池的回收、对类型的卸载,回售条件比较苛刻,经常会导致内存泄漏,当方法区无法满足内存分配时抛出OOM异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值