JVM笔记 2 2 运行时数据区域

本文深入解析Java虚拟机(JVM)的各个内存区域,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区及运行时常量池等,探讨各区域的功能、特点及其异常情况。
1. 程序计数器

简述 程序计数器(program counter register)只占用了一块比较小的内存空间,至于小到什么程度呢,这样说吧,有时可以忽略不计的。可以看作是当前线程所执行的字节码文件(class)的行号指示器。在虚拟机的世界中,字节码解释器就是通过改变计数器的值来选取下一条执行的字节码指令,分支、循环、跳转、异常处理、线程恢复都需要这玩意来实现的

特性 因为处理器在一个确定是时刻只会执行一个线程中的指令,线程切换后,是通过计数器来记录执行痕迹的,因而可以看出,程序计数器是每个线程私有的。 如果执行的是java方法,那么记录的是正在执行的虚拟机字节码指令的地址的地址,如果是native方法,计数器的值为空(undefined)。 这个内存区域是唯一一个在java虚拟界规范中没有规定任何OutOfMemoryError的情况的区域。(只是简单的计数应该不会出现这样的错误吧

2. Java虚拟机栈

简述 虚拟机栈(Java Virtual Machine Stacks) 也是线程私有的,他的生命周期和线程一样,是描述Java方法执行的内存模型。在方法执行的时候创建栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息,就是俗称的Java内存区的堆内存和栈内存中的栈内存。

特性 如果请求深度大于虚拟机允许的深度会报Stack OverflowError异常,如果虚拟机栈可以动态扩展,那么扩展的时候无法申请到足够内存就会报OOMError异常

3. 本地方法栈

简述 与虚拟机栈发挥功能非常相像,只不过虚拟机栈是对Java方法服务,本地方法栈为Native方法服务,有的虚拟机栈,比如HotSpot虚拟机直接将他们两者合一

4. Java 堆

简述 一般是虚拟机内存管理内存中最大的一块,被所有线程共享,几乎所有的对象实例都在这上面分配,但随着JIT编译器的发展和逃逸技术逐渐成熟,栈上分配,标量替换优化技术会导致在堆上分配也不那么绝对了

特性 从内存回收来看,现在的收集器基本都使用了分代收集算法,所以Java堆中基本可以细分为 新生代和老年代,再细致点可以分为Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区),关于堆的详细说明和垃圾回收会在第三章提起,Java堆可以处于物理上不连续的内存空间,只要在逻辑上是连续的就可以了,如果没有内存完成实例分配,堆也无法再次扩展的时候,将会抛出OOMError异常

5. 方法区

简述 也是线程共享,用于存储虚拟机加载的类信息,常量,静态变量等数据,别名叫 Non-Heap,多被称为永久代,实际上并不等价,只是因为HotSpot虚拟机的设计团代用永久代来实现方法区,目前正在逐渐放弃永久代改用Native Mermory 来实现方法区,无法满足内存分配需求的时候也会抛出OOM

6. 运行时常量池

简述 ⽅法区的⼀部分,存放编译期⽣成的各种字⾯量和符号引 ⽤。

7. 直接内存

简述 不属于 运⾏时数据区域,通过NIO类通过Native函数库直接分配堆外内存,然后通过一个存储在堆中的DirectByteBuffer作为内存的引用进行操作,可以避免在Java堆和Native堆中来回复制数据,不受Java堆大小限制,但是还是受到本地内存大小等限制,仍然会出现OOM

转载于:https://juejin.im/post/5a31227551882560e356a344

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值