第2章 Java内存区域与内存溢出异常
运行数据区域
1、程序计数器(Program Counter Register) 是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。
2、Java虚拟机栈(Stack)线程私有,每一个方法调用时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。局部变量存放了编译期可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double)、对象引用(reference类型)和returnAddress类型。
3、本地方法栈(Native Method Stack),为虚拟机的本地方法提供的栈
4、java堆(Heap) 所有线程共享的一块内存区域,存放对象实例。可能会被分为:新生代和老年代。再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。
5、方法区(Method Area) 各纯种共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。通常被 称为 永久代(Permanent Generation)
6、运行时常量池(Runtime Constant Pool)是方法区的一部分,用于存放编译期生成的各种 字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
7、直接内存(Direct Memory)
HotSpot虚拟机对象探秘
对象创建
1、虚拟机遇到一个new指今,检查这个指今参数是否能在常量池中定位。
2、检查这个符号引用代表的类是否已被加载解析和初始化
如果没有先执行相应的类加载过程。
3、分配内存,对象所需内存的大小在类加载完成后便可完全确定。
4、将分配的内存空间都初始化为零值,这一步保证了对象的实例字段在java代码中可以不赋初始值就直接使用。
5、虚拟机对对象进行必要的设置,如何才能找到类的元数据信息、对象的哈希码、对象的GC分代等这些信息存放在对象的对象头中
6、构造函数
对象的内存布局:可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)
对象的访问定位:
通过句柄访问对象
对过直接指针访问对象