jvm的运行时数据结构

781 阅读5分钟

JvM的运行师数据结构

一.程序计数器

  1. 程序计数器是一块较小的内存空间,可以看作是当前线程执行字节码的行号。
  2. 是线程私有的内存。
  3. 唯一一个没有规定OutOfMemoryError异常的内存区域。

二.java虚拟机栈

  1. 是线程私有的内存。
  2. 如果栈不支持动态扩展他可能会抛出StackOverFlowError,如果支持动态扩展可能会抛出OutOfMemoryError。
  3. 每个方法的开始到结束对应一个栈帧在虚拟机栈入栈帆出栈的过程,虚拟机栈只有栈顶的栈帧有效,称为当前栈帧,对应的方法称为当前方法!栈帧主要包括,局部变量表,操作数栈,动态链接和方法出口等信息。
(1)局部变量表主要存储方法参数和方法内的局部变量。
(2)局部变量表中的数据,由于是线程私有的,所以不存在线程安全的问题。
(3)虚拟机是使用局部变量表完成参数值到参数变量列表传递的过程,如果执行的是实例方法,第0位是方法所属实例对象的引用,可以通过this关键字引用到,其余方法参数按照顺序继续存储,存完将方法中的局部变量在按照顺序进行存储。
(4)局部变量表中的空间是可以重用的,也就是说超过了变量的作用域,也就是超过了pc寄存器的值,那么变量我们可以重用其内存空间!
(5)局部变量表中的变量必须赋初始值以后才可以使用,类变量有准备(后续会讲)的过程,所以如果不赋值,默认值为0.
(6)操作数栈还没有想好措辞暂不记录。(我的理解就是数进行计算的过程,相当操作系统各种计数器,比如加法寄存器)
(7)动态链接,每个栈帧都有一个该方法所求引用,为了支持方法调用时动态链接。
(8)方法调用传递的是字节码中的符号引用,如果在类加载阶段或者第一次使用的时候转化为直接引用,这种称为静态解析,如果在运行的过程中转化为直接引用称为动态链接。
(9)退出一个方法有两种方法,字节码指令遇到任意返回指令时!另一种是遇到异常,并且没有匹配到异常处理器时!
(10)方法退出等于当前栈帧出栈,并且恢复上层方法的局部变量表和操作数栈,并且把返回值压入调用者操作数栈中,调整pc寄存器的值!

三.本地方法栈

  1. 本地方法栈和虚拟机栈的作用类似,区别是虚拟机栈为虚拟机之下的java方法服务,本地方法栈为虚拟机使用的Native方法使用.
  2. 本地方法栈也会抛出StackOverFlowError和OutOfMemoryError异常.

四.堆

  1. java堆是所有线程共享的内存区域.
  2. 可以对堆进行划分,比如可以分为老年代,新生代.或者可以分为eden区和survivor区等等,以后会对各种区域进行详细的介绍.
  3. 堆可能会抛出OutOfMemoryError异常.

五.方法区

  1. 方法区是各个线程共享的内存区域.
  2. 它用于存储虚拟机加载的类信息,常量,静态变量,还有即使编译以后的代码等等数据.
  3. 方法区也会抛出OutOfMemoryError异常.

jvm对象创建的过程

  1. 虚拟机遇到一条new指令时,首先检查这个参数能否在常量池中定位到一个类的符号引用.并且检查这个类是否被加载解析和初始化过,如果没有,进行类的加载解析初始化过程.
  2. 类加载解析初始化过后,接下来,虚拟机为新生对象分配内存,对象锁需要的内存可以在类加载过以后确定其大小.

(1).假设java的内存时决定规整的,所有用过的内存放一边,没有使用的内存放在另一边,中间放着一个指针作为分界点的指示器,那分配内存就仅仅是把指针向着空闲空间的那边移动一段与对象大小相等的空间,这种分配方式称为指针碰撞.
(2).如果java中的堆不是绝对规整的可以使用空闲列表的方式,就是已经使用的空间和没有使用的空间交错进行,虚拟机维护一个列表,记录哪块内存是可用的对象进行内存分配的时候在列表中找到一个足够大的空间进行分配,并且更新列表.这种方式称为空闲列表.
(3).选择那种方式,由java堆是否规整决定,而java堆是否规整,由采用的垃圾回收器是否带有整理功能决定.
(4)另一个需要注意的点,对象分配内存空间是非常频繁的,在并发的情况下可能会引起县城安全的问题,虚拟机采用CAS的方式进行空间分配,也可以预先给每个线程分配一小块内存空间,称为TLAB(本地线程分配缓冲),在TLAB使用完或者增加新的TLAB的时候,在使用CAS的方式分配内存空间.

  1. 内存空间分配完成以后,虚拟机将分配到的内存空间都初始化为0值.
  2. 接下来虚拟机对对象进行必要的设置,例如这个对象是哪个类的实例,如何才能找到类的元数据信息, 对象的哈希码,对象的GC年龄等信息.
  3. 到这里,在虚拟机的角度一个新的对象已经产生,但是从java的视角来看,一个对象的创建刚刚开始,方法还没有执行,所有字段还都为0,接下来会执行方法,一个对象才算完整的生产出来.

我是菜鸟,希望大家多多留言讨论~谢谢!

我的笔记是看完深入理解java虚拟机的体会,是本好书,推荐给大家.