读《深入理解Java虚拟机》- Java内存区域

Java的运行时数据区被划分为5给部分,分别是:

程序计数器

java虚拟机栈

本地方法栈

Java堆

方法区

前面三个是线程私有的,后面两个是线程共享的。

1、程序计数器

程序计数器是一块很小的空间,Java虚拟机规范没有规定此内存会产生OOM。

它是当前线程执行到哪里的行号指示器,可以理解为是当前线程执行的字节码的地址。字节码解释器在工作时就是通过改变这个计数器来选取下一条需要执行的指令。

在多线程环境下,线程切换时会保存当前程序计数器的值,以便在线程恢复执行的时候能够从上次切换的地方开始执行。所以这也需要每个线程都拥有一个程序计数器,即线程私有。

另外,在执行本地方法时,程序计数器的值为空(undefined)

2、Java虚拟机栈

Java虚拟机栈也是线程私有的,它描述的是Java方法执行的内存模型,在执行一个Java方法的时候,会创建一个栈帧。栈帧存储了局部变量表,操作数栈,动态链接,方法出口。

局部变量表存放了编译时期就知道的基本数据类型,对象引用(Reference类型的,就是指向对象的指针),局部变量表的需要的空间在编译期间就确定了,并且在运行期间不会改变。

这里会产生两种异常:

StackOverflowError:线程请求栈的深度超过虚拟机规定的最大深度(即方法调方法)

OutOfMemoryError:如果虚拟机栈设置了动态扩展,那么在扩展时没有足够的内存了,就会抛出OOM

3、本地方法栈

类似Java虚拟机栈,上面是普通的Java方法,这里是native方法。同样也有这两个异常。

4、Java堆

Java堆是对象分配的区域,也是垃圾频繁回收的区域,所以也叫GC堆,它是线程共享的。

所有的对象实例以及数组都要在堆上分配(现在也不一定了。。。时代在发展啊)

Java堆按垃圾回收可以分为新生代和老年代,进一步可以划分为Eden区,From Survivor区,To Survivor区。

从线程共享角度来说,堆中还可以划分出线程私有的分配缓冲区:Thread Local Allocation Buffer

以上两种划分都和存放的内容无关,存放的都是对象实例。

Java堆可以处于物理上不连续逻辑上是连续的。堆的大小是可扩展的,用-Xmx -Xms控制。没内存了会抛出OOM

5、方法区

线程共享的区域,存储了已加载的类信息,常量,静态变量,即时编译器编译后的代码。别名叫非堆(non-heap)

方法区很少发生gc,gc的时候主要是对常量池和类型卸载进行回收,回收效率低。

常量池的内容并非在编译期才能产生,也可以在运行时动态产生,例如String.intern().

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值