浅谈Java虚拟机(二)

时间:2022-12-26 17:15:58

        在上一篇文章《浅谈Java虚拟机》中,我们从操作系统方面解释了一下JVM,那么这一篇文章,我们就浅谈一下JVM的内存区域如有表述不当的地方,还请斧正

JVM在运行时的数据区域组成:

1、程序计数器Program Counter Register

2、Java虚拟机栈(Java Vitual Machine Stack)

3、本地方法栈(Native Method Stack

4、Java堆(Java Heap)

5、方法区(Method Area)

6、运行时常量池(Runtime Constant Pool)

浅谈Java虚拟机(二)

一、程序计数器

1、概述: 该区域分配了一块较小的内存空间,它可以看做是当前线程所执行的字节码的信号指示器

2、作用: 通过改变计数器的值来指定下一条需要执行的字节码指令,来恢复中断前程序运行的位置

3、特点:

(1)线程私有化:每个线程都有个独立的程序计数器,来恢复线程前执行的位置

(2)无内存溢出

二、Java虚拟机栈

1、概述:Java方法执行的内存模型,每个方法从调用直至执行的过程,对应着一个栈帧在虚拟机栈中入栈到出栈的过程

2、作用:每个方法被执行的时候,都会创建一个栈帧来存储局部变量表、操作数栈、动态链接、方法出口等信息

3、特点:

(1)线程私有化

(2)生命周期与线程执行结束相同

4、局部变量表

 (1)存放了编译期间可知的各种基本数据类型(8种)、对象引用、returnAddress类型(指向一条字节码指令的地址)

 (2)占用空间:64位长度的long和double类型占用2个局部变量空间(Slot),其余数据类型只占用1个

 (3)分配时机:在编译期间完全分配,当进入一个方法时,占整个方法所需要在帧中分配多大的局部空间空间是完全确定的,在方法运行期间不会改变局部变量表的大小

5、异常

异常类型 发生条件
*Error 线程请求的栈深度大于虚拟机所允许的深度时抛出该异常
OutOfMemoryError 无法申请到足够的内存时抛出该异常

三、本地方法栈

1、概述:与虚拟机栈类似,不过是为虚拟机使用到的Native方法服务的内存区域

2、与虚拟机栈的区别:

     (1)虚拟机栈:为虚拟机执行Java方法(字节码)服务

     (2)本地方法栈:为虚拟机使用到的Native方法服务

3、异常:与虚拟机栈一样

异常类型 发生条件
*Error 线程请求的栈深度大于虚拟机所允许的深度时抛出该异常
OutOfMemoryError 无法申请到足够的内存时抛出该异常

四、Java堆

1、创建时间:JVM启动时创建该区域

2、占用空间:该区域是JVM所管理的内存中最大的一块区域

3、作用:用于存放了对象实例以及数组(所有new的对象)

4、特点:

    (1)垃圾收集器(GC)作用于该区域,回收不使用的对象的内存空间

    (2)各个线程共享(读和写)的内存区域

    (3)该区域的大小可通过-Xms(最小值)和-Xmx(最大值)参数设置,通常这两个值是设成一样的(为避免在运行时频繁调整堆的大小)

五、方法区

1、概述:JVM规范将方法区描述为堆的一个逻辑部分,但是它的别名叫做Non-Heap(非堆),目的是与Java堆区分开

2、占用空间:默认最小值为16M,默认最大为64M

3、作用 :用于存储JVM加载的类信息、常量、静态变量、是各个线程共享的内存区域

4、特点:

    (1)各个线程共享(读和写)的内存区域

    (2)该区域的大小限制可以通过-XX:PermSize和-XX:MaxPermSize参数

5、异常:

异常类型 发生条件
OutOfMemoryError 当方法区无法满足内存分配需求时,抛出该异常

六、运行时常量池

1、概述:方法区的一部分。class文件中除了有类的(版本,字段,方法,接口)等描述信息外,还有一项信息就是常量池

2、作用:用于存放编译期生成的各种 字面量和 符号引用

3、动态性:

    (1)Java并不要求常量池一定只有编译期才能产生,也就是并非预置入class文件中常量池的内容后才能进入方法区的运行时常量池,运行期间也可以将新的常量放入池中

    (2)此特性用的比较广泛的地方就是String类的intern()方法

4、异常:

异常类型 发生条件
OutOfMemoryError 因为它是方法区的一部分,所以是受到方法区内存的限制,当常量池无法再申请到内存时,抛出该异常

七、直接内存

1、概述:

    (1)直接内存不属于虚拟机运行时数据区的一部分,也不是JVM规范中定义的内存区域

    (2)这部分内存也会被频繁使用,而且也有可能导致OutOfMemoryError出现

2、作用:

    (1)在NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作

    (2)提高性能,因为避免了再Java堆和Native堆中来回复制数据

3、异常

异常类型 发生条件
OutOfMemoryError 受到物理内存限制,动态扩展时无法申请到内存时,抛出该异常