深入了解 JVM虚拟机
Posted 知物电子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入了解 JVM虚拟机相关的知识,希望对你有一定的参考价值。
Java虚拟机内存管理
程序计数器
较小的区域,可以看作当前线程执行的字节码的行号指示器,且每个线程都有自己独立的程序计数器。此区域没有规定内存溢出的情况,因为
我们开发人员不会操作到此区域
。
Java虚拟机栈
(先进后出)为虚拟机执行Java方法服务,存放栈帧(每个栈帧对应一个方法)。
每个方法执行都会创建栈帧,栈帧中包含局部变量表、返回值地址等信息。栈帧创建好,方法开始执行,待方法执行完 毕,栈帧出栈,随后就会被销毁。
举例:若A方法中调用了B方法,创建A的栈帧,进入栈,开始执行A方法,执行到A调用B的时候,创建B的栈帧,进入栈,开始执行B方法,B方法执行完毕后,B的栈帧出栈,随后被销毁。A方法继续执行余下部分,直至执行完毕,A的栈帧出栈,随后被销毁。
在使用递归的时候,如果处理不好临界值,很容易就会出现栈内存溢出问题(StackOverFlow)
本地方法栈
为虚拟机执行native方法服务(Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:定义被native关键字修饰的接口,该接口的实现由非java语言实现),其他与虚拟机栈完全一致。
Java堆
用于存放对象的实例,是垃圾回收器的主要工作区域,分为
新生代
和
老年代
,新生代中又划分Eden区,Survivor1区和Survivor2区,当堆内存不足的时候,就会抛出OutOfMemory异常,我们可以通过-Xms和-Xmx来指定堆内存空间。
方法堆
存储虚拟机加载的类的信息(字段,方法,接口),常量,静态变量以及编译器编译之后的代码。当方法区内存不足的时候,就会抛出OutOfMemory异常。方法区很重要的一部分就是运行时常量池,在类和方法被加载到JVM中,对应的运行时常量池就被创建出来,并非Class文件常量池中的内容才能进入运行时常量池,在运行期间也可将新的常量放入运行时常量池中,比如String的intern方法。
对象
对象的创建
New 类名 → 根据new的参数在常量池中定位一个类的符号引用 → 如果当前常量池中没有这个符号引用,说明这个类还没有被加载,则进行类的加载,解析和初始化 → 虚拟机为对象在堆中分配内存 → 将分配的内存初始化(不包括对象头) → 调用对象的
<init>
方法(构造方法等)
对象的结构
Header(对象头)
自身运行时数据(Mark Word)
哈希值
GC分代年龄
锁状态标志
线程持有的锁
偏向线程ID
偏向时间戳
类型指针
InstanceData实例数据
接下来的实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种:类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。这部分的存储顺序会受到虚拟机分配策略参数.(FieldsAllocationStyle)和字段在java源码中定:义顺序的影响。在满足这个前提条件的情况下,在父类中定义的变量会由现在子类之前。如果CompactFields 参数值为true(默认为true);那么子类之中较窄的变量也可能会插入到父类变量的空隙之中。
Padding
第三部分对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。
由HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的小必须是8字节的整数倍。
而对象买部分正好是8字节的倍数(1倍或者2倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。
以上是关于深入了解 JVM虚拟机的主要内容,如果未能解决你的问题,请参考以下文章
深入了解JVM——虚拟机类加载机制
深入了解JVM——虚拟机字节码执行引擎
深入了解JVM——虚拟机字节码执行引擎
《深入理解JVM虚拟机》读书笔记
深入了解JVM——虚拟机性能监控与故障处理工具
深入了解JVM——虚拟机性能监控与故障处理工具