注意:本文基于JDK7来说明,JDK8会有一定小的变化
1.运行时数据区域
2.程序计数器
(1)线程私有
(2)程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。
(3)工作方式:字节码解释器工作时,就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成
3.java虚拟机栈
(1)线程私有
(2)生命周期和线程相同
(3)虚拟机栈描述的是java方法执行的内存模型:
每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
(4)注意:目前所指的栈,只是虚拟机栈的一部分,也就是局部变量表,存放了编译器可知的各种基本类型、对象的引用
4.本地方法栈
线程私有
存放虚拟机使用到的Native方法服务
5.java 堆
(1)线程共享
(2)存放对象实例以及数组
(3)在回收的角度来看(分代收集算法)可以细分为:新生代和老年代(具体介绍:内存分配)
6.方法区
(1)线程共享
(2)存储已被虚拟机价值的类信息、常量、静态变量、即时编译器编译后的代码等数据
(3)在HotSpot虚拟机中又叫永久代
(4)在JDK1.8中,HotSpot已经没有“PermGen space”这个区间了,取而代之是Metaspace(元空间),元空间不再与堆连续,而且是存在于本地内存(Native memory)。
本地内存(Native memory),也称为C-Heap,是供JVM自身进程使用的。当Java Heap空间不足时会触发GC,但Native memory空间不够却不会触发GC。
7.运行时常量池
(1)属于方法区的一部分
(2)用于存放编译器生产的各种字面量和符号引用,,这部分内容将在类加载后进入方法区的运行时常量池中存放
8.对象的创建
(1)创建对象方式:克隆、反序列化、new、反射(克隆和反序列化基于构造器创建对象)
(2)创建过程:
<1>虚拟机需要一条new指令事,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被价值、解析和初始化过。如果没有,那就必须执行相应的类加载过程。(类加载过程会在后面说到)
<2>类加载检查通过后,接下来就是为新生对象分配内存(通过指针碰撞或者空闲列表方式分配内存)
<3>内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值
<4>接下里,虚拟机啊要对对象进行必要的设置,例如这个对象事那个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄信息
<5>以上从虚拟机的角度来看,一个新的对象已经产生了,但从java程序的角度看,对象才刚刚开始,因你init方法还没有执行,执行new方法之后再执行<init>方法把对象按程序员的意愿进行初始化。