jvm-运行时方法区


运行时数据区 (Run-Time Data Areas)

Java虚拟机在程序执行期间定义了各种运行时数据区,一部分数据区的生命周期与Java虚拟机一致,另一部分数据区的生命周期与线程一致。

1. 程序计数器 (program counter register)

  1. 程序计数器是线程私有的,生命周期随线程而生而灭。
  2. 在任何时候,每个线程都在执行一个方法。如果该方法是native方法,程序计数器会存储当前jvm指令的内存地址。反之,程序计数器的值将不会被定义。
  3. 程序计数器(空间)足够大,可以保存一个returnAddress类型的值或者特定平台上的本地指针。

2. Java虚拟机栈 (java virtual machine stacks)

  1. Java虚拟机栈是线程私有的,生命周期随线程而生而灭。
  2. Java虚拟机栈的使用的内存可以是不连续的。
  3. Java虚拟机栈存储栈帧。每个方法从调用到执行完成的过程,对应着一个栈帧在Java虚拟机栈中的压栈弹栈的过程。
  4. Java虚拟机栈可以具有固定大小,也可以根据计算要求动态扩展或收缩。
  5. 如果Java虚拟机允许动态扩展,但是扩展时却无法申请到足够的内存,则会抛出OutOfMemoryError异常。
  6. 如果线程请求分配的栈容量大于Java虚拟机栈允许的最大容量,则会抛出StackOverflowError异常。

3. 堆 (heap)

  1. 堆存储对象实例。
  2. 堆内存可以是不连续的。
  3. 堆是线程共享的,生命周期与Java虚拟机一致。
  4. 堆可以是固定大小,也可以根据需求动态扩展和收缩。
  5. 只要Java虚拟机中的对象不断被创建,且保证GC Roots到对象之间有可达路径来避免垃圾回收机制,当堆存储的对象到达堆内存允许的最大容量时,会抛出OutOfMemoryError异常。

4. 方法区 (method area)

  1. 方法区是线程共享的,生命周期与Java虚拟机一致
  2. 方法区存储类信息,运行时常量池(runtime constant pool),字,方法数据,JIT编译后的代码数据,以及类和接口初始化的函数<clinit>和类实例初始化的函数<init>等信息。
  3. 方法区在逻辑上是的一部分,但是两者应该区分来看。
  4. 方法区的内存区域可以是不连续的。
  5. 方法区的大小可以是固定的,也可以根据需求动态的扩缩容。
  6. 如果无法提供方法区中的内存来满足分配的请求,会抛出OutOfMemoryError异常。

5. 运行时常量池 (runtime constant pool)

  1. 每个运行时常量池都是从Java虚拟机的方法区中分配的
  2. 运行时常量池主要用于存放编译期生成的各种字面量和符号引用,以及在运行时解析的方法和字段引用。
  3. 创建类或接口时,如果运行时常量池构造所需的内存超过Java虚拟机的方法区域中可用的内存,则Java虚拟机将抛出OutOfMemoryError

6. 本地方法栈 (native method stacks)

  1. 本地方法栈和Java虚拟机栈很相似。
  2. 本地方法栈也是线程私有的,并且也能抛出OutOfMemoryError,StackOverflowError异常。
  3. 本地方法栈为虚拟机使所使用到的native方法服务。
  4. Java虚拟机中并没有限制实现native方法的语言,使用方式和数据结构,因此具体的虚拟机可以自由的实现它。
  5. 有的虚拟机(Sun HotSpot虚拟机)直接把本地方法栈和虚拟机栈合并在一起

文章作者: iamazy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 iamazy !
  目录