上图是jdk1.6的内存区域图,1.7将运行时常量池移到了堆中,1.8则是在1.7的基础上去除了方法区,增加了元空间。
1、程序计数器
程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。它是线程私有的,此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
2、java虚拟机栈
它与计数器一样也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的java方法执行的内存模型,每个方法执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程都对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
3、本地方法栈
本地方法栈。与虚拟机栈功能类似,不过是作用于native方法。
4、java堆
对大多数应用来说,java堆是java虚拟机所管理的内存中最大的一块。java堆是被所有线程共享的一块内存区域,它的作用就是用来存放对象实例,几乎所有的对象实例都在这里分配。因为几乎是所有对象的存放区域,所以也是gc的主要区域了。
5、方法区
方法区与java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
6、运行时常量池
运行时常量池是方法区的一部分。
7、直接内存
在JDK1.4中新加入了NIO类,引入了一种基于通道与缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能再一些场景中显著提高性能,因为避免了再java堆和Native堆中来回复制数据。
1、对象的创建
创建的方式有“指针碰撞”与“空闲列表”。
2、对象的内存布局
在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头、实例数据和对齐填充。
对象头
HotSpot虚拟机的对象头包括两部分信息,第一部门用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。
对象头的另外以部门是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
实例数据
是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。
对齐填充
它仅仅起着占位符的作用。
3、对象的访问定位
目前主流的访问方式有使用句柄和直接指针两种。
摘自:《深入理解java虚拟机》