深入理解Java虚拟机之运行时数据区域

来源:互联网 发布:最强大脑人工智能小度 编辑:程序博客网 时间:2024/05/16 11:08

深入理解Java虚拟机之运行时数据区域

JVM在java程序运行时会将它所管理的内存分为不同的区域,这些区域都要不同的用途和各自的创建销毁时间,主要包含下面几个区域:

  • 程序计数器
  • Java虚拟机栈
  • 本地方法栈
  • Java堆
  • 方法区
  • 运行时常量池(属于方法区)

下面我们来分别介绍一下这些区域的作用以及所包含的内容。

  • 1、
    程序计数器,是线程私有的,是一块较小的内存区域,可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的字节码解释器工作时,就是通过程序计数器来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依靠它来完成。这个区域也是Java虚拟机规范中唯一没有规定任何OutOfMemoryError的区域。

  • 2、Java虚拟机栈,同程序计数器一样,也是线程私有的,所以它的生命周期就和线程是一样的,随着线程的创建而创建,随着线程的销毁而销毁。而我们常说的JVM内存分为堆和栈并不是说真的就只分为堆和栈两块,而是我们主要关注的就是这两块,其中栈就是我们现在说的虚拟机栈,Java虚拟机栈主要用于存储线程的局部变量表、操作数栈、动态链接、方法出入口等信息,方法的调用就是栈帧在虚拟机栈中入栈出栈的过程。在局部变量表中主要存放了编译期即可知道的各种基本数据类型(byte、boolean、char、short、int、float、double、long)和引用(引用就是指向一个对象存储的起始位置的指针或者指向一个代表对象的句柄)以及returnAddress类型。在Java虚拟机栈中会抛出两种异常,当线程请求的栈深度大于虚拟机栈所允许的深度的时候会抛出StackOverflowError异常,当虚拟机栈在动态扩展的时候无法申请的足够的内存时会抛出OutOfMemoryError异常。

  • 3、本地方法栈,和虚拟机栈是很类似的只不过Java虚拟机栈是为Java方法服务,而本地方法栈则是为虚拟机使用到的Native方法服务,在有的虚拟机中直接将本地方法栈和Java虚拟机栈合二为一。和虚拟机栈一样,本地方法栈一样会抛出StackOverflowError异常和OutOfMemoryError异常。

  • 4、Java堆,对一般的应用来说,堆是JVM管理内存中最大的一块。堆是被所有线程所共享的一块内存区域,主要用于存放对象实例,基本上所有的对象实例以及数组都要在堆上进行分配。正因为如此,所以堆而是垃圾收集器的主要管理部分,所以堆也称之为GC堆。根据现在收集器基于分代收集的算法,堆可以分为新生代和老年代,而新生代又可以细分为Eden区、From Survivor区和To Survivor区。堆也可能会划分出多个线程私有的分配缓冲区也叫TLAB。在虚拟机配置中我们可以通过设置-Xmx和-Xms来力控制堆的大小,当堆无法进行扩展的时候会抛出OutOfMemoryError异常。

  • 5、方法区,和堆一样也是线程共享的一块内存区域,主要用于存储已经被虚拟机加载进来的类的信息、常量、静态变量、即时编译期编译后的代码等数据,有时候我们也会把方法区归到堆里面,成为堆的一个逻辑部分,而由于在这个区域进行内存回收的目标主要是常量池中的常量以及类型的卸载,由于Java虚拟机类型的卸载条件非常苛刻,所以也有很多人称呼方法区为永久代,当然本质上这两者并不相等,永久代也不是真正的永久。当方法区无法满足内存分配的需求时将会抛出OutOfMemoryError异常。

  • 6、运行时常量池,是方法区的一部分,主要用于存在Class在编译期生成的各种字面量和符号引用。当然常量池具有动态性,并不要求常量只能在编译期产生,也并不是只能在编译期进入常量池,运行期间也可能有新的常量放入池中,比方说我们最熟悉的String类的intern()方法,和方法区一样当常量池无法申请到内存的时候会抛出OutOfMemoryError异常。

以上就是对Java虚拟机运行时的数据区域进行的大概介绍。

阅读全文
0 0
原创粉丝点击