pc:根据计数器中的值来选取下一条需要执行的字节码指令。任何一个确定的时刻,一个处理器都只会执行一条线程中的指令,为了线程切换后能恢复到正确的执行位置, 每条线程都需要有一个独立的程序计数器。各条线程之间的计数器互不影响, 独立存储, 称这类内存区域为’线程私有’。
线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时会创建一个栈帧用于存储局部变量表、 操作数栈、 动态链接、 方法出口等信息。 **每一个方法从调用直至执行完成的过程, 就对应着一个栈帧在虚拟机中入栈到出栈的过程。
局部变量表存放了编译器可知的各种基本数据类型、 对象引用类型和returnAddress类型。局部变量表所需的内存空间是在编译期间完成分配, 当进入一个方法时, 这个方法需要在帧中分配多大的局部变量空间时完全确定的, 在方法运行期间不会改变局部变量表的大小。
Native Method:简单地讲,一个Native Method就是一个java调用非java代码的接口。
本地方法栈与虚拟机栈发挥的作用时非常相似的, 区别不过时虚拟机栈为Java方法服务, 本地方法栈则为虚拟机使用到的Native方法服务。–>功能与虚拟机栈相似, 服务对象不同. 线程私有的
Java堆时被所有线程共享的一块内存区域, 在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,堆也是垃圾收集器管理的主要区域, 因此很多时候被称为GC堆。堆可以处于物理上不连续的内存空间, 只要逻辑上时连续的即可。
线程共享的内存区域, 它用于存储已被虚拟机加载的类信息、 常量、 静态变量、 即时编译器编译后的代码等数据。运行时常量池是方法区的一部分。用于存储编译期生成的各种字面量和符号引用。
通常时针对Java堆的。
复制算法(Copying):将可用内存按容量大小划分为大小相等的两块。每次只使用其中一块,当这一块内存用完了, 就将还存活着的对象复制到另外一块上面, 然后再把已使用过的内存空间一次清理掉。实现简单,运行高效。但代价是将内存缩小为了原来的一半,过多了。 目前都采用这种收集算法来回收新生代。
标记-整理算法(Mark-Compact):复制收集算法在对象存活率较高时就要进行较多的复制操作,效率变低。根据老年代的特点,提出了标记-整理算法。标记过程标记-清除算法一样, 但后续步骤不是直接堆可回收对象进行清理, 而是让所有存活的对象都向一端移动, 然后直接清理掉端边界以外的内存。
新生代:Eden, from-survivor,to-survivor。 8:1:1 老年代:
Java虚拟机中类加载的全过程, 也就是:
加载是类加载过程的一个阶段, 在加载阶段虚拟机需要完成一下三件事:
验证时连接阶段的第一步, 这一阶段的目的时为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求。整体上看, 验证阶段大致上会完成下面4个阶段的检验动作: 文件格式验证、 元数据验证、 字节码验证、 符号引用验证。
正式为类变量(被static修饰的变量)分配内存并设置类变量初始值的阶段, 这些变量所使用的内存都将在方法区中进行分配。这里的初始值通常情况下是数据类型的零值,如果类字段的字段属性为ConstantValue属性那么在准备阶段变量value就会被初始化为ConstantValue属性所指定的值(见value2),假设一个类变量的定义为:
public static int value = 123; //value is 0 在准备阶段
public static final int value2 = 123; // value is 123 在准备阶段
那变量value在准备阶段后的初始值为0而不是123, 把value赋值为123的指令在初始化阶段才会执行。
虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化阶段时执行类构造器方法的过程。