jvm内存结构
- 格式:pdf
- 大小:812.22 KB
- 文档页数:5
JVM工作原理JVM(Java虚拟机)是Java程序的运行环境,它负责将Java源代码编译成可执行的字节码,并提供运行时环境来执行字节码。
JVM的工作原理涉及到类加载、内存管理、垃圾回收、即时编译等多个方面。
1. 类加载JVM通过类加载器(ClassLoader)来加载Java类。
类加载器根据类的全限定名(包括包名和类名)在类路径中查找对应的字节码文件,并将其加载到内存中。
类加载器采用双亲委派模型,即先由父类加载器尝试加载类,如果父类加载器无法加载,则由子类加载器尝试加载。
这种模型保证了类的唯一性和安全性。
2. 内存管理JVM将内存分为多个区域,包括方法区、堆、栈和程序计数器。
方法区存储类的元数据信息,如字段、方法、常量池等。
堆是存放对象实例的区域,通过垃圾回收机制来管理内存的分配和释放。
栈用于存储方法的局部变量和方法调用信息。
程序计数器用于指示当前线程执行的字节码指令。
3. 垃圾回收JVM通过垃圾回收机制自动回收不再使用的对象内存。
垃圾回收器会定期扫描堆内存,标记所有还在使用的对象,然后清理掉未被标记的对象。
常见的垃圾回收算法有标记-清除、复制、标记-整理等。
JVM还提供了不同的垃圾回收器,如Serial、Parallel、CMS、G1等,可以根据应用场景选择合适的垃圾回收器。
4. 即时编译JVM使用即时编译器(Just-In-Time Compiler)将热点代码(经常被执行的代码)编译成本地机器码,以提高执行效率。
JVM会监测程序的运行情况,根据热点代码的执行频率和调用关系进行优化编译。
即时编译器可以选择不同的编译策略,如解释执行、编译执行或混合执行。
5. 内存模型JVM定义了Java程序在多线程环境下的内存模型,保证多线程的内存可见性和有序性。
内存模型规定了线程之间如何进行通信和同步。
JVM使用主内存和工作内存的概念,线程之间的共享变量存储在主内存中,每个线程有自己的工作内存,线程对共享变量的操作先在工作内存中进行,然后通过主内存来同步和通信。
面试谈jvm原理Java虚拟机(JVM)是Java语言运行的基础。
JVM具有封装性、跨平台性、高度优化和可扩展性等特点,是Java应用程序的核心。
在Java的诞生初期,由于硬件环境和操作系统制约,JVM起到了垫底的作用。
而今天,JVM已经成为Java 运行效率和安全性的保障。
下面是一些我认为JVM原理面试时可能会涉及的重点:1. JVM的内存模型:JVM将内存分为堆内存和栈内存,堆内存用于存储对象实例和数组,而栈内存则用于存储方法的执行状态。
同时,JVM还有方法区和永久代的概念。
这些内存区域的大小和分配情况会影响JVM的性能和稳定性。
2. 垃圾回收机制:JVM的内存管理包括垃圾回收机制和内存分配机制。
垃圾回收机制是JVM实现自动内存管理的核心,JVM会周期性地扫描堆内存中没有被引用的对象,并自动回收它们所占用的内存。
垃圾回收机制常用的算法包括标记清除、复制和标记整理等。
3. 类加载机制:Java程序在运行时,需要将类文件中的二进制数据加载到JVM 中,才能执行相应的操作。
类加载机制将类文件加载到JVM中,并将它们解析为Java类。
类加载机制包括三个阶段:加载、链接和初始化。
4. JIT编译器:JIT(Just In Time)编译器是JVM在运行时动态优化的关键组件。
JIT编译器可以在程序运行时,根据代码的执行情况,生成本地机器代码,以提高程序的效率。
5. JVM调优:JVM的性能和稳定性很大程度上取决于JVM参数的设置和调整。
面试时,可能会涉及到如何根据系统的特点和需求,设置JVM参数以达到最佳性能和稳定性的问题。
总之,有关JVM原理的面试问题,往往涉及到JVM的内存模型、垃圾回收机制、类加载机制、JIT编译器和JVM调优等方面。
需要候选人对这些方面有比较深入的了解。
JVM内存设置方法JVM(Java虚拟机)是Java程序的运行环境,它负责执行Java字节码,并管理程序的内存。
在运行Java程序时,合理地设置JVM的内存大小是非常重要的,它会影响程序的性能和稳定性。
下面是一些关于JVM内存设置的方法和注意事项:1. 初始堆大小(-Xms)和最大堆大小(-Xmx):初始堆大小指定了JVM初始时分配的堆内存大小,最大堆大小则指定了堆内存的上限。
可以通过在启动命令中加上-Xms和-Xmx参数来设置堆内存大小,例如:```java -Xms256m -Xmx512m MyApp```这样就设置了初始堆大小为256MB,最大堆大小为512MB。
2.堆内存的大小选择:堆内存的大小应根据应用程序的需求和服务器硬件条件来选择。
如果堆内存过小,可能会导致OutOfMemoryError;如果堆内存过大,可能会导致频繁的垃圾回收,影响程序的性能。
可以通过监控JVM的堆使用情况来判断是否需要调整堆内存的大小。
可以使用JVM自带的JVisualVM工具或第三方的工具如G1GC日志分析工具进行监控。
3.堆内存的分代设置:堆内存分为新生代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation,JDK8及之前的版本)/元空间(Metaspace,JDK8及之后的版本)。
新生代用于存储新创建的对象,老年代用于存储长时间存活的对象,永久代/元空间用于存储类和方法等信息。
可以通过设置堆内存的分代比例来调整堆内存的大小,例如:```-XX:NewRatio=2```这样就将堆内存的新生代和老年代的大小比例设置为1:2、可以根据应用程序的特点和需求进行调整。
4.非堆内存的设置:非堆内存包括方法区、直接内存等。
可以通过设置参数来调整非堆内存的大小,例如:```-XX:MaxMetaspaceSize=256m```这样就设置了元空间的最大大小为256MB。
jvm规范JVM(Java虚拟机)是Java语言的核心和关键部分,它是在Java程序运行过程中执行字节码的虚拟计算机。
JVM规范(Java Virtual Machine Specification)定义了JVM的结构、行为和规范。
JVM规范的第一部分是关于虚拟机结构的描述。
JVM由如下几个组成部分:类加载器、执行引擎、运行时数据区和本地方法接口。
类加载器负责将字节码文件加载到JVM中,执行引擎则负责执行字节码指令。
运行时数据区包括堆、栈、方法区等,用来存储程序的数据和执行过程中的临时数据。
本地方法接口允许JVM调用本地方法(非Java语言实现的方法)。
JVM规范的第二部分是关于虚拟机指令集的描述。
Java源代码经过编译后生成字节码文件,字节码中包含了一系列指令。
JVM规范定义了这些指令的编码和执行方式。
一些常见的指令包括加载和存储指令、算术和逻辑指令、跳转指令等。
通过这些指令,JVM可以实现各种操作,比如对变量的赋值、条件判断和循环等。
JVM规范的第三部分是关于类文件格式的描述。
Java源代码经过编译后生成的字节码文件就是类文件,它包含了类的结构、字段、方法等信息。
JVM规范定义了类文件的格式,包括魔数、版本号、常量池、访问标志、字段表、方法表等部分。
通过解析类文件,JVM可以加载和验证类的结构,以及执行其中的方法。
JVM规范的第四部分是关于运行时数据区的描述。
运行时数据区包括堆、栈、方法区等部分,它们分别用来存储对象、方法参数和局部变量、类的结构信息等。
JVM规范定义了这些数据区的组织方式和内存分配策略。
比如,堆用于存储对象实例,栈用于存储方法的局部变量和方法参数,方法区用于存储类的结构信息和常量池。
最后,JVM规范还包括一些附录,包括与Java语言关键字的映射、可选的特性和扩展等内容。
这些附录不是必需的,但对于理解和使用JVM是有帮助的。
总结来说,JVM规范是Java程序运行的基础,它定义了JVM 的结构、行为和规范。
jvm stackmaptable原理目录1.JVM 内存结构概述2.StackMapTable 的作用和定义3.StackMapTable 的结构和内容4.StackMapTable 的生成与使用5.StackMapTable 在 JVM 中的重要性正文一、JVM 内存结构概述在 Java 虚拟机(JVM)中,内存结构主要分为堆内存(Heap Memory)和栈内存(Stack Memory)。
堆内存主要用于存储对象实例,而栈内存用于存储局部变量和方法调用。
在 JVM 的栈内存中,有一个重要的数据结构——StackMapTable,它对 Java 程序的运行具有重要意义。
二、StackMapTable 的作用和定义StackMapTable,又称为栈映射表,是一个描述 Java 方法调用过程的数据结构。
它记录了 Java 字节码中每一条指令在栈内存中的位置,以及该指令所操作的栈帧(Stack Frame)的类型。
StackMapTable 在编译阶段由编译器生成,并在程序运行时由 JVM 使用。
三、StackMapTable 的结构和内容StackMapTable 是一个数组,它的每一个元素称为一个栈映射项(Stack Mapping Entry)。
每个栈映射项包含以下三个信息:1.偏移量(Offset):表示该栈映射项在内存中的位置。
2.栈帧类型(Frame Type):表示该栈映射项所对应的栈帧的类型,例如:局部变量、操作数栈、方法调用等。
3.指令索引(Instruction Index):表示该栈映射项对应的 Java 字节码指令在字节码文件中的位置。
四、StackMapTable 的生成与使用1.生成:在编译阶段,编译器会根据 Java 字节码文件生成StackMapTable。
编译器会将每一条字节码指令以及与之相关的栈操作信息(如:入栈、出栈、使用栈顶元素等)记录到 StackMapTable 中。
JVM 原理解释JVM 全称是 Java Virtual Machine ,Java 虚拟机,这个 JVM 你是看不到的,它存在内存中。
我们知道计算机的基本构成是:运算器、控制器、存储器、输入和输出设备,那这个 JVM 也是有这成套的元素,运算器是当然是交给硬件 CPU 还处理了,只是为了适应“一次编译,随处运行”的情况,需要做一个翻译动作,于是就用了JVM 自己的命令集,JVM 的命令集则是可以到处运行的,因为 JVM 做了翻译,根据不同的CPU ,翻译成不同的机器语言。
JVM 是一个内存中的虚拟机,那它的存储就是内存了,我们写的所有类、常量、变量、方法都在内存中。
JVM 的组成部分Class Loader 类加载器类加载器的作用是加载类文件(.class)到内存,Class Loader 加载的 class 文件是有格式要求的。
类加载的最终产品是位于运行时数据区的堆区的Class对象。
Class对象封装了类在方法区内部的数据结构。
并且向JAVA程序提供了访问类在方法区内的数据结构。
JVM加载class文件的原理机制1. Java 中的所有类,必须被装载到 JMV 中才能运行,这个装载工作是由 JVM 中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中。
2. Java中的类大致分为三种:a) 系统类b) 扩展类c) 由程序员自定义的类3. 类装载方式,有两种:a) 隐式装载,程序在运行过程中当碰到通过 new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中。
b) 显式装载,通过 class.forname() 等方法,显式加载需要的类。
4. 类加载的动态性体现一个应用程序总是由n多个类组成,Java 程序启动时,并不是一次把所有的类全部加载后再运行,它总是先把保证程序运行的基础类一次性加载到 JVM 中,其它类等到 JVM 用到的时候再加载,这样的好处是节省了内存的开销。
jvm堆的基本结构
Java虚拟机(JVM)堆是一种重要的内存分配结构,被用来存储Java 类实例和数组,是Java内存管理的重要组成部分。
JVM堆由以下三部分组成:
1.堆栈:堆栈是一种先进后出(LIFO)的内存结构,用于存储Java对象的本地变量。
堆栈空间占用资源比较小,但容量有限,一般比较小(只支持少计数的变量)。
2.程序计数器:程序计数器是一个小巧且独立的内存结构,用于保存执行过程中当前活动线程正在执行的字节码行号。
jvm通过程序计数器控制程序运行,它不会存储任何对象。
3.垃圾回收堆:垃圾回收堆是一种用于存储对象的内存结构,一般由堆顶(Young generation),年老代(Old Generation )和永久代(Permanent Generation)组成。
堆顶是一个存储新生成的对象的内存区域,当堆顶达到容量上限时,部分对象会被转移至年老代;而永久代则用于存放永久数据,如Java类,字段和方法。
总的来说,JVM堆是一个内存结构,用于管理Java对象。
它主要由堆栈、程序计数器和垃圾回收堆组成,通过这三个基本构建块构成JVM
堆,兼顾性能和可维护性。
JVM堆是Java内存管理的重要组成部分,其利用了可伸缩性和性能可控性,是运行Java程序的重要基础。
jvm non heap 默认值Java虚拟机(Java Virtual Machine,简称JVM)是Java平台的核心组件之一,负责执行Java字节码。
JVM管理着Java应用程序的内存,其中包括堆内存(Heap)和非堆内存(Non-Heap)。
本文将重点探讨JVM的非堆内存,并讨论其默认值。
1. 概述非堆内存指的是JVM中用于存放类信息、常量池、静态变量等数据的内存空间。
与堆内存不同的是,非堆内存的内存空间是JVM自行管理的,不会进行垃圾回收。
2. 非堆内存的分类在JVM中,非堆内存主要分为两类:永久代(Permanent Generation)和元空间(Metaspace)。
2.1 永久代(已过时)永久代是Java 7及更早版本中用于存储类信息、常量池等内容的内存区域。
它的大小由`-XX:PermSize`和`-XX:MaxPermSize`参数控制,默认的初始大小为20MB,最大大小为64MB。
然而,永久代在JVM中存在多种问题,例如内存泄漏和内存溢出等。
因此,自Java 8开始,永久代被元空间所取代。
2.2 元空间元空间是Java 8及更高版本中引入的非堆内存区域,用于存储类信息、常量池等内容。
与永久代不同的是,元空间的大小不再受限于固定的堆内存大小,而是可以根据应用程序的需要进行动态调整。
元空间的大小由`-XX:MetaSpaceSize`和`-XX:MaxMetaspaceSize`参数控制,默认的初始大小为21MB,最大大小为无限制(Unlimited)。
3. 非堆内存默认值在大多数情况下,JVM的非堆内存默认值已经足够满足常规的Java应用程序需求。
然而,在某些特殊情况下,可能需要调整非堆内存的默认值以提升性能或解决特定的问题。
3.1 Java虚拟机默认值在没有显式指定非堆内存相关参数的情况下,JVM的默认非堆内存大小的设置如下:- 在Java 7及更早版本中,默认的非堆内存大小为20MB,即永久代的初始大小。
文章标题:深度探讨Java JVM空间担保机制在进行Java编程和开发过程中,我们经常会听到关于Java虚拟机(JVM)的空间担保机制的概念。
这个机制是如何工作的?为什么它如此重要?本篇文章将从深度和广度两个方面对Java JVM空间担保机制进行全面评估,并在此基础上撰写一篇有价值的文章。
让我们回顾一下Java虚拟机的内存结构。
Java虚拟机的内存分为堆内存和栈内存两部分。
堆内存用于存储对象实例,而栈内存则用于存储基本数据类型和对象的引用。
在堆内存的使用过程中,会涉及到内存的分配和回收,而这恰好是空间担保机制所要解决的核心问题。
空间担保机制是Java虚拟机为了保证内存分配的安全而设计的一种机制。
当程序在进行内存分配时,如果发现无法满足当前对象的内存需求,空间担保机制就会进行一次垃圾回收,尝试为新对象腾出空间。
这就意味着,即使堆内存已经快要耗尽,空间担保机制也能够及时地进行垃圾回收,从而保证程序的正常运行。
在实际编程中,我们经常会遇到内存泄漏和内存溢出的问题。
而空间担保机制正是为了解决这些问题而设计的。
通过空间担保机制,程序可以更加灵活地进行内存分配和回收,从而避免了因为内存不足而导致程序崩溃的情况。
从个人的观点来看,Java JVM空间担保机制是Java编程中非常重要的一部分。
它不仅保证了程序的稳定性和健壮性,还使得程序员能够更加专注于程序的逻辑和功能实现,而不用过多地关注内存管理的细节问题。
正因如此,我们需要深入地理解和掌握空间担保机制的工作原理和技术细节,从而更好地进行Java编程和开发工作。
总结而言,Java JVM空间担保机制是Java编程中至关重要的一环。
通过本文的深度探讨,我们可以更加全面、深刻和灵活地理解这一机制。
在日后的编程实践中,我们应该充分利用空间担保机制的优势,避免内存管理的烦恼,从而更好地完成编程任务和项目开发。
希望我的文章能够帮助你更好地理解Java JVM空间担保机制,期待与你共享更多有价值的内容!Java虚拟机(JVM)是一种能够执行Java字节码的虚拟机,它是Java语言的核心和关键部分。
jvm内存模型简单理解JVM内存模型是Java虚拟机中的一个重要概念,它是Java程序运行时内存分配和管理的基础。
JVM内存模型主要包括堆内存、栈内存、方法区和程序计数器等几个部分。
堆内存是Java程序中最大的一块内存区域,用于存储对象实例和数组等动态分配的数据。
堆内存的大小可以通过JVM参数进行调整,一般情况下,堆内存的大小会根据应用程序的需求进行动态调整。
堆内存的分配和回收是由垃圾回收器来完成的,当对象不再被引用时,垃圾回收器会自动回收该对象所占用的内存空间。
栈内存是Java程序中用于存储局部变量和方法调用的一块内存区域。
每个线程都有自己的栈内存,栈内存的大小是固定的,一般情况下,栈内存的大小为1MB。
栈内存的分配和回收是由JVM自动完成的,当方法执行完毕或者线程结束时,栈内存会自动释放。
方法区是Java程序中用于存储类信息、常量、静态变量和方法字节码等数据的一块内存区域。
方法区的大小也可以通过JVM参数进行调整,一般情况下,方法区的大小为64MB。
方法区的分配和回收是由JVM自动完成的,当类被卸载时,方法区中的数据会被自动回收。
程序计数器是Java程序中用于记录当前线程执行的位置的一块内存区域。
程序计数器的大小为一个机器字长,一般情况下,程序计数器的大小为4字节或8字节。
程序计数器的分配和回收是由JVM 自动完成的,当线程结束时,程序计数器会自动释放。
JVM内存模型是Java程序运行时内存分配和管理的基础,它包括堆内存、栈内存、方法区和程序计数器等几个部分。
这些内存区域的分配和回收是由JVM自动完成的,Java程序员只需要关注程序的逻辑实现,而不需要过多关注内存管理的细节。
结构概览
JVM内存区域也称为Java运行时数据区域。
其中包括:程序计数器、栈、堆、方法区等。
内存结构主要分为三大部分:堆内存,方法区和栈。
堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分成三部分,Eden空间、From Survivor空间、To Survivor空间。
方法区存储类信息、常量、静态变量等数据,是线程共享的区域,为与Java堆区分,方法区还有一个别名Non-Heap(非堆);栈又分为java虚拟机栈和本地方法栈主要用于方法的执行。
JVM和系统调用之间的关系:
Java堆(Heap)
Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。
Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。
此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC堆”。
如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。
根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。
在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。
简要归纳:新的对象分配是首先放在年轻代 (Young Generation) 的Eden区,Survivor区作为
Eden区和Old区的缓冲,在Survivor区的对象经历若干次收集仍然存活的,就会被转移到老年代Old中。
方法区(Method Area)
是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据(存放的是Class)。
它有一个别名,叫非堆。
数据在内存中的存放如下:
程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。
字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。
因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互
此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
总结如下:
1. 当前线程所执行的字节码行号指示器。
2. 每个线程都有一个自己的PC计数器。
3. 线程私有的,生命周期与线程相同,随JVM启动而生,JVM关闭而死。
4. 线程执行Java方法时,记录其正在执行的虚拟机字节码指令地址。
5. 线程执行Native方法时,计数器记录为空(Undefined)。
6. 唯一在Java虚拟机规范中没有规定任何OutOfMemoryError情况区域。
JVM栈(JVM Stacks)
是线程私有的,它的生命周期与线程相同。
虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。
每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部变量表
局部变量表是一组变量值的存储空间,用于存储方法参数和局部变量。
在 Class 文件的方法表的 Code 属性的 max_locals 指定了该方法所需局部变量表的最大容量。
局部变量表在编译期间分配内存空间,可以存放编译期的各种变量类型:
1. 基本数据类型:boolean, byte, char, short, int, float, long, double等8种;
2. 对象引用类型:reference,指向对象起始地址的引用指针;
3. 返回地址类型:returnAddress,返回地址的类型。
变量槽是局部变量表的最小单位,规定大小为32位。
对于64位的long和double变量而言,虚拟机会为其分配两个连续的Slot空间。
操作数栈
操作数栈(Operand Stack)也常称为操作栈,是一个后入先出栈。
在 Class 文件的 Code 属性的max_stacks 指定了执行过程中最大的栈深度。
Java虚拟机的解释执行引擎被称为基于栈的执行引擎,其中所指的栈就是指-操作数栈。
1. 和局部变量表一样,操作数栈也是一个以32字长为单位的数组。
2. 虚拟机在操作数栈中可存储的数据类型:int、long、float、double、reference和returnType等
类型 (对于byte、short以及char类型的值在压入到操作数栈之前,也会被转换为int)。
3. 和局部变量表不同的是,它不是通过索引来访问,而是通过标准的栈操作 — 压栈和出栈来访问。
比如,如果某个指令把一个值压入到操作数栈中,稍后另一个指令就可以弹出这个值来使用。
虚拟机把操作数栈作为它的工作区——大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。
动态链接
每个栈帧都包含一个指向运行时常量池中所属的方法引用,持有这个引用是为了支持方法调用过程中的动态链接。
Class文件的常量池中存在有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用为参数。
这些符号引用:
1. 静态解析:一部分会在类加载阶段或第一次使用的时候转化为直接引用(如final、static域等),
称为静态解析,
2. 动态解析:另一部分将在每一次的运行期间转化为直接引用,称为动态链接。
方法返回地址
当一个方法开始执行以后,只有两种方法可以退出当前方法:
1. 正常返回:当执行遇到返回指令,会将返回值传递给上层的方法调用者,这种退出的方式称为正常
完成出口(Normal Method Invocation Completion),一般来说,调用者的PC计数器可以作为返回地址。
2. 异常返回:当执行遇到异常,并且当前方法体内没有得到处理,就会导致方法退出,此时是没有返
回值的,称为异常完成出口(Abrupt Method Invocation Completion),返回地址要通过异常处理器表来确定。
当一个方法返回时,可能依次进行以下3个操作:
1. 恢复上层方法的局部变量表和操作数栈。
2. 把返回值压入调用者栈帧的操作数栈。
3. 将PC计数器的值指向下一条方法指令位置。
本地方法栈(Native Method Stacks)
本地方法栈和Java虚拟机栈发挥的作用非常相似,主要区别是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。