Java 内存管理
Java 虚拟机对内存的划分主要包括:
-
程序计数器
线程私有,用于指示当前线程执行的字节码行号,保证线程切换后能恢复到正确的位置继续执行。此内存区域是唯一一个在 Java 虚拟机规范中没有规定任何 OOM 情况的区域。 -
Java 虚拟机栈
线程私有,其生命周期和线程相同,描述的是 Java 方法执行的内存模型。每个方法从调用到完成,对应着一个栈帧(栈帧在方法执行时创建,用于存储局部变量表,操作数栈等)在虚拟机栈中入栈和出栈的过程。这部分会抛出两种异常(StackOverflowError,OOM)局部变量表
存放着编译器可知的基本数据类型,对象引用(可能仅仅只是引用),returnAddress 类型。 -
Native 方法栈
线程私有,想对于 Java 虚拟机栈,区别仅仅是执行的方法不同,这里执行的是 Native 方法。也会存在( StackOverflowError,OOM) -
Java 堆
线程共享,唯一目的就是用来存放对象实例。这块区域也是垃圾回收器重点工作区域。这里会存在 OOM 异常。 -
方法区
线程共享,存储已被虚拟机加载的静态变量,常量,类信息等,运行时常量池也是该区域的一部分(存放类加载后的常量池)。这里会存在 OOM 异常。
对象的创建
对象的创建
一个对象通过虚拟机创建通常会经过:
-
类加载过程
-
为新生对象分配内存
-
为内存空间进行初始化
-
对对象进行必要的设置
完成上述步骤后,在虚拟机的角度看,对象已经生成,而从应用程序的角度看对象才刚开始创建(因为初始化还没开始),只有紧接着完成初始化操作,对象才算真正的产生并可以使用。
对象的组成
对象在内存中的组成可分为:
-
对象头
-
实例数据
-
对齐填充
对我们而言,需要关心的就是 实例数据 部分,包含了代码中定义的各种变量。
对象的访问
还记得在 Java 虚拟机栈中的局部变量表 中存储的对象引用吗?应用程序就是通过那部分的数据来操作 Java 堆上的具体对象。具体访问对象的方式有:
-
句柄访问
优点是对象引用始终存储的是句柄地址,不随垃圾回收器清理 Java 堆时,对象被移动而改变。 -
直接指针
优点是速度更快。
网友评论