JVM内存区域划分

JVM内存区域划分

内存区域概念

由于java依赖于JVM实现跨平台,对于不同的平台,JVM对内存分配和内存管理都具有一套统一的规范。其中JVM的内存区域一般分为:堆(heap),虚拟机栈(VM stack),本地方法栈(Native Method Stack),方法区(Method Area),程序计数器(Program Counter Register)五大区域。每个区域都有其特性,会影响内存溢出和垃圾回收情况。大致情况如下图:
在这里插入图片描述

一、虚拟机栈

平常就简称为栈,是JVM中线程不共享的一块区域,他的生命周期和线程的相同。该区域是存贮方法执行的内存。在方法执行时,会产生一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。大致情况如下图:
在这里插入图片描述
每个栈帧就代表着当前线程中调用的方法,其中最上方的栈帧代表着当前线程正在执行的方法。细分下来,局部变量表存贮着函数的局部变量,相当于一个数组。操作数栈是方法进行运算的地方,与局部变量表不同的是它的使用方式是通过压栈和弹栈来实现的,比方说计算在方法中有局部变量a,b,c。当进行c=a+b运算时,a和b进行弹栈操作,执行运算,再将结果压入操作数栈当中。动态链接,每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。方法返回地址记录着当前栈帧出栈后的函数返回地址。
相信很容易看出来,既然栈内存是用来存贮栈帧的,那么在该区域内存溢出的产生原因就是程序的方法调用栈过深,例如我们在编写递归程序的时候,递归出口不正确,导致的内存溢出。此时抛出的异常是StackOverflowError。当我们设置的虚拟机可以动态扩展时,就可以一直压栈,直到动态扩展无法再申请内存,此时会抛出OutOfMemoryError异常。

二、本地方法栈

本地方法栈和栈空间极其类似,不过存储在其中的方法是native的方法,如Object的wait(),hashCode()这样的方法,这些方法不是使用java来实现的,一般是C++实现。调用这些函数时所需内存就存贮在本地方法区中,过多的native函数调用也会使此区域OutOfMemory

三、堆内存

堆内存是一块线程共享的区域,java中绝大部分对象实例都存贮在堆内存之上,有时,如逃逸分析时,对象不会分配在堆上。对象的初始化细节后面会提到。由于堆上的对象大部分都是朝生夕死的,所以这一块也是JavaGC的重点区域,采用分代收集的JVM还会分为年轻代,永久代,这里就不一一说明。既然该区域是用于存储实例的,那么在给新的实例分配内存时,却无可用内存,也无法扩展时,就会抛出OutOfMemory异常。

四、方法区

存贮着加载的类信息,常亮,静态变量等,这一块不太熟悉,不敢乱说,占坑,后期补充

五、程序计数器

可以看做是当前当前线程所执行的字节码行号指示器,为了使程序在线程切换后能恢复到正确的执行位置,每条线程都要有一个独立的程序计数器。可能是由于存储的信息很少,在JVM中没有对这块区域规定OutOfMemory的情况。

总结

以上只是对JVM区域划分有个笼统的介绍,先让人有个大概的认知。后期会其加以补充,下期介绍下OOM的具体情况,以及具体分析。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值