文章目录
- 1、官网概括
- 2、图例和思维导图
- 3、方法区(Method Area)
- 4、堆(Heap)
- 5、Java虚拟机栈
- 6、 栈帧(Stack Frame)
- 7、程序计数器(The pc Register)
- 8、本地方法栈(Native Method Stacks)
1、官网概括
引用官网说法:
运行时数据区,是java虚拟机定义的在程序执行期间使用的各种运行时的数据区。这些运行时数据区分为两种,一种是在java虚拟机启动时创建,仅在java虚拟机退出时才被销毁,这种可以理解为线程共享的。另外一种是数据区是针对每个线程的,是在创建线程时创建的,并在线程退出时销毁这个数据区,这种可以理解为线程私有的。
2、图例和思维导图
JVM运行时数据区图例:
思维导图:Java虚拟机运行时数据区,虚拟机栈、本地方法栈、程序计数器是线程私有的,方法区、堆是线程共享的
3、方法区(Method Area)
那么what is method area? 什么是方法区呢?
下面摘录官网对方法区的描述
(1)方法区是线程共享的内存区域,在虚拟机启动时创建
(2)虽然方法区是堆的一个逻辑部分,但是其别名为非堆(Non-heap),目的是和堆区分开
(3)方法区存储运行时常量池、字段和方法数据,以及方法和构造函数的代码,包括在类和实例初始化和接口初始化中使用的特殊方法
ps,注意点:如果方法区中的内存不能用于满足分配请求,Java 虚拟机将抛出一个OutOfMemoryError.
小总结:
JVM方法区中存储了每个类的信息(包括类的名称、方法信息、字段信息),静态变量,常量已经编译器编译后的代码等。
方法区是线程共享的,习惯上方法区也被称为“永久代”。如果方法区中的内存不能用于满足分配请求,Java 虚拟机将抛出内存不足异常
4、堆(Heap)
(1)Java堆是Java虚拟机所管理内存中最大的一块,堆是运行时数据区,从中分配所有类实例和数组的内存
(2)堆是在虚拟机启动时创建的,是所有 Java 虚拟机线程之间共享的
注意:如果计算需要的堆多于自动存储管理系统所能提供的堆,Java 虚拟机将抛出一个 OutOfMemoryError.
小总结:
Java 中的堆是用来存储对象本身的以及数组,堆是被所有 线程共享的。
Java 堆从 GC 的角度还可以细分为: 新生代( Eden 区 、 From Survivor 区 和 To Survivor 区 )和老年代。如果计算需要的堆多于自动存储管理系统所能提供的堆,Java 虚拟机将抛出一个 OutOfMemoryError.
5、Java虚拟机栈
Java虚拟机栈:Java Virtual Machine Stacks
(1)每一个java虚拟机线程都有一个java虚拟机栈,在线程创建时候就创建虚拟机栈
(2)java虚拟机线程中的每一个方法对应一个栈帧;调用一个方法,就向虚拟机栈中压入一个栈帧;一个方法调用完成,就将改栈帧从栈中弹出
6、 栈帧(Stack Frame)
栈帧:每个栈帧对应一个被调用的方法,可以理解为一个方法的运行空间
每个栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、动态链接(Dynamic Linking)、方法返回地址(Return Address)
- 局部变量表:方法中定义的局部变量以及方法的参数存放在这张表
- 操作数栈:以压栈和出栈的方式存储操作数的
- 动态链接:每个帧都包含对当前方法类型的运行时常量池的引用,以支持方法代码的动态链接,class方法的文件代码指的是要调用的方法和要通过符号引用访问的变量。动态链接将这些符号方法引用转换为具体方法引用,根据需要加载类以解析尚未定义的符号,并将变量访问转换为与这些变量的运行时位置相关联的存储结构中的适当偏移量(重点理解一下符号方法引用转换为具体方法引用,class文件编译为字节码之后,会有一个符号引用规范,动态链接就是将符号方法引用转换为具体方法引用)
- 方法返回地址:当一个方法开始执行后,只有两种方式可以退出,一种是遇到方法返回的字节码指令;一种是遇见异常,并且该异常不在方法内处理,则方法调用会 突然完成。执行athrow指令 ( § athrow ) 也会导致显式抛出异常,如果当前方法未捕获异常,则会导致方法调用突然完成。突然完成的方法调用永远不会向其调用者返回值。
注意:如果线程中的计算需要比允许的更大的 Java 虚拟机堆栈,则 Java 虚拟机将抛出一个StackOverflowError.
如果 Java 虚拟机堆栈可以动态扩展,并且尝试扩展但没有足够的内存来实现扩展,或者如果没有足够的内存可以为新线程创建初始 Java 虚拟机堆栈,则 Java 虚拟机机器抛出一个OutOfMemoryError.
7、程序计数器(The pc Register)
每个java虚拟机线程都有自己的程序计数器。在任何时候,每个 Java 虚拟机线程都在执行单个方法的代码,如果该方法不是 native,则该pc寄存器包含当前正在执行的 Java 虚拟机指令的地址。如果线程当前正在执行的方法是native,则 Java 虚拟机pc 寄存器的值是未定义的
8、本地方法栈(Native Method Stacks)
对于一般的方法,都是在java虚拟机栈指向,如果当前线程执行的方法是Native类型的,这些方法就会在本地方法栈中执行,学习本地方法栈可以和虚拟机栈对比。
native方法实例,可以点到String源码里看,如图,这个方法就是一个native方法:
异常情况:
- 栈深度大于已有深度:StackOverflowError
- 可扩展深度大于能够申请的内存:OutOfMemoryError
转载:https://www.jb51.net/article/214130.htm#_label0