1. 运行时数据区域
1.1 方法区
方法区是各个线程共享的内存区域,用于存储类的信息、常量。静态变量、即时编译器编译后的代码等数据,大小通过-XX:PermSize和-XX:MaxPermSize控制;还有一个别名为Non-Heap(非堆)和永久代。
1.2 堆
虚拟机启动时创建,是各个线程共享的内存区域,唯一目的就是存放对象实例,堆的大小通过-Xmx和-Xms控制,设置一样,即避免自动扩展,提高性能;还可以细分为新生代和老年代。
1.3 虚拟机栈
线程私有内存,生命周期与线程一致;每一个方法执行时都创建一个栈帧用来存储局部变量表、操作数栈、动态链接、方法出口等信息。局部变量表存放了各种基本数据类型、对象引用;可以通过-Xss参数设定。
1.4 本地方法栈
1.5 程序计数器
程序计数器是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器。
2. 虚拟机对象探秘
2.1 对象的创建
2.2 对象的内存布局
对象在内存中存储的布局分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
2.3 对象的访问定位
两种方式,句柄(栈中存有对象的句柄地址,然后句柄中存储了实例数据和类型数据的指针)和直接指针(栈中直接存有对象的实例数据的指针);一般使用直接指针。
3. 实战内存溢出
3.1 Java堆溢出
通过参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆快照以便事后分析。