面试必问的JVM知识-JVM特性学习( 二 )


运行时常量池运行时常量池(Runtime Constant Pool)是方法区的一部分 。 Class文件中除了有类的版本、字段、方法、接口等描述信息外 , 还有一项信息是常量池表(Constant Pool Table) , 用于存放编译期生成的各种字面量与符号引用 , 这部分内容将在类加载后存放到方法区的运行时常量池中 。
运行时常量池是方法区的一部分 , 当常量池无法再申请到内存时会抛出OutOfMemoryError异常 。
直接内存直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分 , 但是这部分内存也被频繁地使用 , 而且也可能导致OutOfMemoryError异常出现 。
对象在HotSpot虚拟机里 , 对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例 数据(Instance Data)和对齐填充(Padding) 。
HotSpot虚拟机对象的对象头部分包括两类信息 。 第一类是用于存储对象自身的运行时数据 , 也叫"Mark Word" 。 "Mark Word"信息如下:
面试必问的JVM知识-JVM特性学习文章插图
Mark Word
我们的Java程序会通过栈上的reference数据来操作堆上的具体对象 。 主流的访问方式主要有使用句柄和直接指针两种 。
句柄访问:Java堆中将可能会划分出一块内存来作为句柄池 , reference中存储的就是对象的句柄地址 , 而句柄中包含了对象实例数据与类型数据各自具体的地址信息
直接指针访问: , Java堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息 , reference中存储的直接就是对象地址 , 如果只是访问对象本身的话 , 就不需要多一次间接访问的开销
一般HotSpot虚拟机使用的是第二种直接指针访问 。
面试必问的JVM知识-JVM特性学习文章插图
直接指针
这里我提出一个问题 , 大家可以思考:
【面试必问的JVM知识-JVM特性学习】如何写出堆溢出异常和栈溢出异常的代码?
这个是面试常被问到的问题 。 关于堆溢出异常 , 可以从创建对象 , 让对象撑爆堆内存方面思考;关于栈溢出异常 , 可以考虑如何让栈帧塞满栈 。