JVM内存区域
运行时数据区域
线程独占
- 程序计数器
- 虚拟机栈
- 本地方法栈
*虚拟机栈和本地方法栈中都有可能出现StackOverflowError和OutOfMemoryError
线程共享
- Java堆(用于存放对象实例和数组,大部分对象都存放于此)
- 新生代:Eden, From Survivor, To Survivor
- 老年代
- 方法区(JDK1.8后变成元空间,放在本地内存中)
- 用于储存类信息、常量、静态变量、JIT编译后的代码等数据
- 运行时常量池(属于方法区的一部分)
- 直接内存(实际上不属于运行时数据区,但是也会被经常使用)
*堆的细分目的是方便内存分配和垃圾回收
对象创建过程
- 类加载检查
- 检查在常量池中是否可以定位到这个类的符号引用,并检查是否已经加载、解析和初始化过。若没有,则先进行类加载
- 为对象分配内存
- 类加载完成后,便可以确定其对象所需的内存大小,由此对象分配内存。
- 在分配内存时,根据堆内存是否规整采用指针碰撞(Bump the Pointer)或空闲列表(Free List)方法
- 为了保证内存分配的原子性,可以采用:CAS(Compare And Swap)+失败重试方式/按照线程在不同空间中分配的方式(采用 本地线程分配缓冲 TLAB)
- 初始化零值
- 设置对象头
- 对象头中保存对象相关信息:对象属于哪个类、如何找到类的元数据、对象的哈希值、GC分代年龄等
- 执行init方法
- 根据程序编写者的意愿进行初始化