当前位置: 首页 > news >正文

【JVM】虚拟机栈与本地方法栈

一、虚拟机栈(VM Stack)
1.1)什么是虚拟机栈
  虚拟机栈是用于描述java方法执行的内存模型。
  每个java方法在执行时,会创建一个“栈帧(stack frame)”,栈帧的结构分为“局部变量表、操作数栈、动态链接、方法出口”几个部分(具体的作用会在字节码执行引擎章节中讲到,这里只需要了解栈帧是一个方法执行时所需要数据的结构)。我们常说的“堆内存、栈内存”中的“栈内存”指的便是虚拟机栈,确切地说,指的是虚拟机栈的栈帧中的局部变量表,因为这里存放了一个方法的所有局部变量。
  方法调用时,创建栈帧,并压入虚拟机栈;方法执行完毕,栈帧出栈并被销毁,如下图所示:
在这里插入图片描述

1.2)虚拟机栈的特点
虚拟机栈是线程隔离的,即每个线程都有自己独立的虚拟机栈。

1.3)虚拟机栈的StackOverflowError
  若单个线程请求的栈深度大于虚拟机允许的深度,则会抛出StackOverflowError(栈溢出错误)。
  JVM会为每个线程的虚拟机栈分配一定的内存大小(-Xss参数),因此虚拟机栈能够容纳的栈帧数量是有限的,若栈帧不断进栈而不出栈,最终会导致当前线程虚拟机栈的内存空间耗尽,典型如一个无结束条件的递归函数调用,代码见下:

/*** java栈溢出StackOverFlowError* JVM参数:-Xss128k* Created by chenjunyi on 2018/4/25.*/
public class JavaVMStackSOF {private int stackLength = -1;//通过递归调用造成StackOverFlowErrorpublic void stackLeak() {stackLength++;stackLeak();}public static void main(String[] args) {JavaVMStackSOF oom = new JavaVMStackSOF();try {oom.stackLeak();} catch (Throwable e) {System.out.println("Stack length:" + oom.stackLength);e.printStackTrace();}}}

设置单个线程的虚拟机栈内存大小为128K,执行main方法后,抛出了StackOverflow异常

Stack length:983
java.lang.StackOverflowErrorat com.manayi.study.jvm.chapter2._02_JavaVMStackSOF.stackLeak(_02_JavaVMStackSOF.java:14)at com.manayi.study.jvm.chapter2._02_JavaVMStackSOF.stackLeak(_02_JavaVMStackSOF.java:15)at com.manayi.study.jvm.chapter2._02_JavaVMStackSOF.stackLeak(_02_JavaVMStackSOF.java:15)······

1.4)虚拟机栈的OutOfMemoryError

不同于StackOverflowError,OutOfMemoryError指的是当整个虚拟机栈内存耗尽,并且无法再申请到新的内存时抛出的异常。
  JVM未提供设置整个虚拟机栈占用内存的配置参数。虚拟机栈的最大内存大致上等于“JVM进程能占用的最大内存(依赖于具体操作系统) - 最大堆内存 - 最大方法区内存 - 程序计数器内存(可以忽略不计) - JVM进程本身消耗内存”。当虚拟机栈能够使用的最大内存被耗尽后,便会抛出OutOfMemoryError,可以通过不断开启新的线程来模拟这种异常,代码如下:

/*** java栈溢出OutOfMemoryError* JVM参数:-Xss2m* Created by chenjunyi on 2018/4/25.*/
public class JavaVMStackOOM {private void dontStop() {while (true) {}}//通过不断的创建新的线程使Stack内存耗尽public void stackLeakByThread() {while (true) {Thread thread = new Thread(() -> dontStop());thread.start();}}public static void main(String[] args) {JavaVMStackOOM oom = new _03_JavaVMStackOOM();oom.stackLeakByThread();}}

设置单个线程虚拟机栈的占用内存为2m并不断生成新的线程,最终虚拟机栈无法申请到新的内存,抛出异常:
Exception in thread “main” java.lang.OutOfMemoryError: unable to create new native thread
二、本地方法栈(Native Method Stack)

本地方法栈的功能和特点类似于虚拟机栈,均具有线程隔离的特点以及都能抛出StackOverflowError和OutOfMemoryError异常。
  不同的是,本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。如何去服务native方法?native方法使用什么语言实现?怎么组织像栈帧这种为了服务方法的数据结构?虚拟机规范并未给出强制规定,因此不同的虚拟机实可以进行自由实现,我们常用的HotSpot虚拟机选择合并了虚拟机栈和本地方法栈。

相关文章:

  • redis—String字符串
  • 【unity学习笔记】3.常用结构体
  • MyBatis——MyBatis的缓存
  • TrustZone之与非安全虚拟化交互
  • docker-compose 安装Sonar并集成gitlab
  • 构造LR(1)分析表和LALR(1)分析表
  • 晶闸管(Thyristor)
  • 【数据结构和算法】找到最高海拔
  • 2023.12.24力扣每日一题——收集足够苹果的最小花园周长
  • 搭建react+ant design pro+umi 项目框架
  • 自动驾驶中的“雷达”
  • 使用代码生成器生成代码 mybatis-plus-generator
  • 酷开科技,斩获“2023年度广告主金伙伴”等重量级奖项
  • Maven仓库依赖导入‘.lastUpadate‘问题解决
  • 【AI】阿里云免费GPU服务资源领取方法
  • [LeetCode] Wiggle Sort
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • express.js的介绍及使用
  • golang中接口赋值与方法集
  • Hibernate最全面试题
  • IDEA 插件开发入门教程
  • JS函数式编程 数组部分风格 ES6版
  • log4j2输出到kafka
  • Swift 中的尾递归和蹦床
  • yii2权限控制rbac之rule详细讲解
  • yii2中session跨域名的问题
  • 程序员该如何有效的找工作?
  • 对象引论
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 删除表内多余的重复数据
  • 我的zsh配置, 2019最新方案
  • 学习使用ExpressJS 4.0中的新Router
  • 用jquery写贪吃蛇
  • Prometheus VS InfluxDB
  • 仓管云——企业云erp功能有哪些?
  • 交换综合实验一
  • 树莓派用上kodexplorer也能玩成私有网盘
  • #define,static,const,三种常量的区别
  • #HarmonyOS:Web组件的使用
  • #NOIP 2014# day.1 T2 联合权值
  • (13)Hive调优——动态分区导致的小文件问题
  • (7)STL算法之交换赋值
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (多级缓存)缓存同步
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (转)项目管理杂谈-我所期望的新人
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET 事件模型教程(二)
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • :=
  • [ HTML + CSS + Javascript ] 复盘尝试制作 2048 小游戏时遇到的问题
  • [20171113]修改表结构删除列相关问题4.txt
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项