JVM 运行时数据区详解

     1、PC寄存器(线程独有):全称是程序计数寄存器,它记载着每一个线程当前运行的JAVA方法的地址,如果是当前执行的是native方法,则程序计数器会是一个空地址。它的作用就是用来支持多线程,线程的阻塞、恢复、挂起等一系列操作。这个内存区域是唯一一个在虚拟机中没有规定任何OutOfMemoryError情况的区域。

     2、JAVA虚拟机栈(线程独有)JAVA虚拟机栈是在创建线程的同时创建的,生命周期与线程相同。每个方法被执行的时候都会同时创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法从被调用到执行完成,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

  • 栈帧:简单点说,可以解释为是一个方法运行时,临时数据的存储区域,具体点说,它里面包括了数据和部分的过程结果,与此同时,它又肩负着处理方法返回值、动态链接以及异常分派的任务。栈帧是随着方法的创建而创建,随着方法的结束而销毁,如果方法抛出异常,也算方法结束。然而在每一个栈帧中,都有着自己的局部变量表以及操作数栈以及对当前类的运行时常量池的引用。
  • 局部变量表:在编译时期就写入了class文件当中,所需的内存空间在编译期间完成分配。简单的理解,可以将它理解为一个对象数组,而里面按照索引0到length-1分别对应于每一个局部变量,特别的,如果是实例方法的局部变量表,第0个局部变量会是一个指向当前实例的引用,也就是this关键字,其余的局部变量则从索引1开始。
  • 操作数栈它是一个后进先出(LIFO)栈,而它的长度也是在编译时期就写入了class文件当中,是固定的。它的作用就是提供字节码指令操作变量计算的空间,比如简单的,对于int a=9这句话来说,就需要先将9压入操作数栈,再将9赋给a这个变量。

     3、本地方法栈(线程独有)它用来支持native方法的执行。如果JAVA虚拟机是使用的其它语言实现指令集解释器的时候,也会用到本地方法栈。如果某个虚拟机实现的native方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。

    public static native long currentTimeMillis();

     4、JAVA堆(全局共享)堆随着JAVA虚拟机的启动创建,储存着所有对象实例以及数组对象,而且内置了“自动内存管理系统”,也就是我们常说的垃圾搜集器(GC)。JAVA堆中的内存释放是不受开发人员控制的,完全由JAVA虚拟机一手操办。对于JAVA虚拟机如何实现垃圾搜集器,JAVA虚拟机规范没有明确的规定,也正因如此,我们平时使用的JAVA虚拟机中提供了许多种垃圾搜集器,它们采用不同的算法以及实现方式,已满足多方面的性能需求。

由于现在收集器基本采用分代手机算法,所以JAVA堆还可以细分为“新生代”和“老年代”;新生代再细致一点的有Eden空间、From Survivor空间、To Survivor空间等,一般情况,Eden空间占80%,Survivor各占10%。

 

     5、方法区(全局共享):方法区也是堆的一个组成部分,也叫非堆,它主要存储的是运行时常量池、静态变量、类信息、字段信息、方法信息、构造方法与普通函数的字节码内容以及一些特殊方法。垃圾收集行为在这个区域是比较少出现的,主要针对常量池和类型卸载。在HotSpot虚拟机中,用永久代来实现方法区,将GC分代收集扩展至方法区,但是这样容易遇到内存溢出的问题。JDK1.7中,已经把放在永久代的字符串常量池移到堆中。JDK1.8撤销永久代,引入元空间(动态扩容)。

运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。运行期间也可以将新的常量放入池中,比如String类的intern()方法。

猜你喜欢

转载自blog.csdn.net/Anenan/article/details/83786076
今日推荐