一、运行时数据区
1.计数器
当前线程所执行的字节码的行号指示器
2.虚拟机栈
线程私有 每个方法在执行时会创建一个栈帧,
3.本地方法栈
4.java堆
所有线程共享的一块内存区域,所有对象实例和数组都在堆上分配内存。
-Xmx -Xms
5.方法区
线程共享,存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码
方法区无法满足内存分配需求,内存泄露OutOfMemoryError
5.1运行时常量池
运行时常量池具备动态性,运行期间也可将新的常量放入池中
HotSpot虚拟机
永久代 -XX:MaxPermSize
二、HotSpot虚拟机在java堆中对象分配、布局和访问的全过程
本地线程分配缓冲(Thread Local Allocation Buffer)
虚拟机是否使用TLAB -XX:+/-UseTLAB
2.1对象创建
new指令,类加载-->为新生对象分配内存,对象所需大小在类加载完后可确定。-->将分配到的内存空间都初始化为零值-->对对象进行必要的设置(类的元数据信息、对象的哈希码、对象的gc分代年龄,这些信息存放在对象的对象头中Object Header)-->init方法
内存分配完成后,虚拟机需要将分配到的内存空间初始化为零值。这一步操作保证了对象的实例对象在java代码总可以不赋值就
直接使用,程序能访问到这些字段的数据类型所对应的零值。
2.2对象的内存布局
对象在内存中存储布局分为:对象头、实例数据、对齐填充
对象头:第一部分:存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳。
另一部分是类型指针,即对象指向它的类元数据的指针。
实例数据:对象真正存储的有效信息,在程序代码中所定义的各种类型的字段内容。存储顺序受到虚拟机分配策略参数和字段在java源码中定义顺序的影响。HotSpot虚拟机默认 的分配策略为long/doubles、ints、shorts/chars、bytes/booleans、oops(Ordinary Object Points)普通对象指针。
对齐填充:起着占位符的作用。HotSpot VM自动内存管理系统要求对象起始地址是8字节的整数倍,即对象的大小必须是8字节的整数倍。而对象头大小是8字节的倍数。当对象实例数据部分没有对齐时,就需要对齐填充来补全。
2.3访问定位
java虚拟机栈中的reference类型存放对象的引用。访问具体对象目前有2种方式。句柄和直接指针。
若采用句柄访问,则reference中存储的是句柄池的地址,句柄中包含了对象实例数据与类型数据各自的具体地址信息。
若采用直接指针访问,则reference中存储的是对象的地址。(是对象类型数据的还是对象实例数据的?)