深入理解Java虚拟机-1:Java内存区域

本文详细介绍了Java虚拟机的内存区域,包括程序计数器、虚拟机栈、本地方法栈、堆、方法区(包括运行时常量池)以及直接内存。每个区域的作用、线程级别和异常情况如StackOverflowError和OutOfMemoryError均有阐述,特别是堆和方法区的变化以及垃圾回收机制。此外,还提及了直接内存与NIO的关系以及其在内存管理中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

阅读《深入理解Java虚拟机》相关笔记.

内存区域

Java运行时内存区域

  • 程序计数器
  • 虚拟机栈
  • 本地方法栈
  • 方法区

程序计数器

线程级别
可以看作是当前线程所执行的字节码的行号指示器。
《Java虚拟机规范》唯一没有规定任何OutOfMemoryError情况的区域。

虚拟机栈

线程级别

  • 局部变量表

线程所请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError。
如果栈容量可以动态扩展,无法申请到足够的内存,抛出OutOfMemoryError。

本地方法栈

线程级别
为虚拟机使用到的本地方法服务,native关键字。native方法主要用于加载文件和动态链接库,由于Java语言无法访问操作系统底层信息(比如:底层硬件设备等),这时候就需要借助C语言来完成了。被native修饰的方法可以被C语言重写。
与虚拟机栈一样在栈深度溢出或栈扩展失败时分别抛出StackOverflowError和OutOfMemoryError。

所有线程共享
Java Heap是虚拟机所管理的内存中最大的一块。唯一目的就是存放对象实例。《Java虚拟机规范》描述:“所有的对象实例以及数组都应当在堆上分配”。但就目前技术发展的态势看,渐渐不是那么绝对了。实现上日后可能出现值类型的支持。
Java堆是垃圾回收器管理的区域(so-called GC Heap)。现代大部分垃圾回收器是基于分代收集理论设计的(新生代,老年代,永久代)。当然也有不采用分代设计的新垃圾回收器。
从分配内存的角度而言,Java堆可以划分多个线程私有的分配缓冲区(Thread Local Allocation Buffer, TLAB)。但这些划分都是为了更快,更好的分配和回收内存。无论哪个区域,存储的都只能是对象的实例

Java堆既可以是固定大小,也可以是可扩展的。当Java堆中没有内存分配给实例,也没法再扩展时,抛出OutOfMemeoryError。

方法区

所有线程共享
用于存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。别名“非堆”(Non-Heap)。
JDK8以前,当时HotSpot团队将垃圾回收器的分代设计扩展至方法区,从而省去专门为方法区编写内存管理代码的工作,当时使用永久代实现方法区,导致更容易遇到内存溢出问题(永久代有-XX:MaxPermSize上限以及默认大小)。JDK8完全抛弃了永久代的概念,改用与JRockit、J9一样在本地内存中实现的元空间(Metaspace)。
垃圾回收行为再方法区确实是比较少实现的,但并非数据进入了方法区就永久存在了。方法区内存回收的主要目标是常量池回收和类型的卸载。类型卸载条件相当苛刻,回收效果很难令人满意,但有时又确实必要。低版本的HotSpot中一些Bug就是对该区域未完全回收导致的内存泄漏。
无法满足内存新的内存分配需求时,抛出OutOfMemoryError。

运行时常量池

Runtime Constant Pool是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息,还有一项信息是常量池表,用于存储编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区运行时常量池中。
《Java虚拟机规范》并没有做细节要求,但一般来说,除了保存Class文件中描述的符号引用外,还会把由符号引用翻译出来的直接引用也存储在运行时常量池中。
运行时常量池的动态性,运行期间也可以将新的产量放入池中,利用较多的是String类的intern()方法。
受到方法区内存的限制,当常量池无法申请到内存时,抛出OutOfMemoryError。

直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》定义的内存区域。
在JDK1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,可以使用Native函数库直接分配对外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值