Java内存区域与内存溢出异常——深入理解Java虚拟机读书笔记(一)

运行时内存区域

在这里插入图片描述

程序计数器 Program Counter Register(线程私有)

程序计数器是当前线程所执行的字节码的行号指示器,字节码解释器工作时会通过改变程序计数器的值来选取下一条需要运行的字节码指令。

执行Java方法-记录正在执行的虚拟机字节码指令的地址
执行Native方法-空(Undefined)
*不会出现OutOfMemoryError

虚拟机栈 VM Stack(线程私有)

描述的是Java方法执行的内存模型:每个方法被执行的时候都会创建一个栈帧(Stack Frame)用于储存局部变量表、操作栈、动态链接、方法出口等信息。
局部变量表所需的内存空间在编译期间完成分配,在方法运行期间不会改变局部变量表的大小。局部变量表存放的是编译期可知的基本数据类型、对象引用、以及ReturnAddress类型。
有两种可能的异常:
*StackOverflowError:线程请求的栈深度大于虚拟机允许的深度
*OutOfMemoryError:虚拟机栈动态扩展时无法申请到足够的内存

本地方法栈 Native Method Stack (线程私有)

与虚拟机栈类似,本地方法栈是为虚拟机使用到的Native方法。
(HotSpot虚拟机把本地方法栈和虚拟机栈合二为一)
异常类型与虚拟机栈相同。

Java堆 Heap (线程共享)

Heap是被所有线程共享的一块内存区域,在虚拟机启动时创建。
Heap唯一作用是存放对象实例,几乎所有的对象实例以及数组都要在堆上分配。
是GC管理的主要区域。
Java堆可以处于物理上不连续的内存空间中,只要逻辑上连续即可。
主流的虚拟机都是可以对Java堆进行扩展的(通过-Xmx和-Xms控制)。
如果没有内存完成实例的分配且无法扩展时,会抛出OutOfMemoryError异常。

方法区 Method Area(线程共享)

存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
在这个区域里很少会出现GC行为(这个区域GC主要针对常量池的回收和对类型的卸载)
方法区无法满足内存分配需求时,会抛出OutOfMemoryError异常

运行时常量池 Runtime Constant Pool

是方法区的一部分。
Class文件除了有类的版本、字段、方法、接口等,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后放到方法区的运行时常量池中。一般来说,虚拟机会把符号引用翻译出来的直接引用也存储在运行时常量池中。
具备动态性,并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中(最常用的是String类的intern()方法)
当运行时常量池无法再申请到内存时会抛出OutOfMemoryError异常。

直接内存

直接内存并不是运行时数据区的一部分,但也会被频繁使用,而且可能导致OutOfMemoryError异常出现。
**JDK1.4中新加入NIO类引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。**这样做避免在Java堆和Native堆中来回复制数据。

对象访问

对于下面这句代码
Object obj = new Object();
涉及到 Java栈,堆,方法区三个最重要的内存区域之间的关联关系。
Object obj 这部分会反应到Java栈的本地变量表中,作为一个引用reference类型出现。
new Object(); 这部分会反映到Java堆中,形成一块储存Object类型所有实例数据值的结构化内存,根据具体类型以及虚拟机实现的对象内存分布局的不同,这块内存长度是不固定的。
在Java堆中还必须包含能查找到此对象类型数据的地址信息,(如对象类型、父类、实现的接口、方法等),这些类型数据储存在方法区。

对于reference类型,主流的访问方式有两种:使用句柄,和直接指针
使用句柄:Java堆划分一块内存作为句柄池,reference中储存的是对象的句柄地址,句柄中包含对象实例数据类型数据各自的具体地址信息。
通过句柄访问对象
直接指针:reference中直接储存对象地址
通过直接指针访问对象
两种方式各有优势,句柄访问的好处是reference中存储的是稳定的句柄地址,在对象被移动的时候只会改变句柄中的实例数据指针(GC时移动对象是很普遍的行为),reference本身不需要修改。
使用直接指针访问的最大好处就是速度更快,节省一次指针定位的时间开销。
对于Sun HotSpot而言,它是使用第二种方式进行对象访问的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值