程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Java底层 - JVM

    • JVM - Java体系结构
    • JVM - 类加载子系统
    • JVM - 运行时数据区概述及线程
    • JVM - 程序计数器
    • JVM - 虚拟机栈
    • JVM - 本地方法接口
    • JVM - 本地方法栈
      • 1. 本地方法栈 (Native Method Stack) 概述
      • 2. 本地方法栈的特性
      • 3. 本地方法栈与本地方法的执行
      • 4. JVM 规范与实现差异
      • 5. HotSpot 虚拟机的实现
    • JVM - 堆 (Heap)
    • JVM - 方法区
    • JVM - 对象实例化内存布局
    • JVM - 直接内存管理
    • JVM - 执行引擎
    • JVM - 字符串常量池 (StringTable)
    • JVM - 垃圾回收概述
    • JVM - 垃圾回收相关算法
    • JVM - 垃圾回收相关概念
    • JVM - 垃圾回收器
    • JVM - Class文件结构
    • JVM - 字节码指令集与解析
    • JVM - 类的加载过程详解
    • JVM - 再谈类的加载器
    • JVM - 调优概述
    • JVM - 监控及诊断工具cmd
    • JVM - 监控及诊断工具GUI
    • JVM - 运行时参数
    • JVM - 分析GC日志
  • Java底层
  • Java底层 - JVM
scholar
2024-01-18
目录

JVM - 本地方法栈

# 1. 本地方法栈 (Native Method Stack) 概述

在 JVM 的运行时数据区中,除了我们熟知的用于管理 Java 方法调用的虚拟机栈 (VM Stack) 之外,还存在一个专门服务于本地方法 (Native Method) 调用的内存区域——本地方法栈 (Native Method Stack)。

核心职责区分:

  • Java 虚拟机栈 (VM Stack):管理 Java 方法的调用。每个 Java 方法的执行对应一个栈帧在虚拟机栈上的入栈和出栈。
  • 本地方法栈 (Native Method Stack):管理 本地方法的调用。当线程调用一个 native 关键字修饰的方法时,其执行状态的管理就由本地方法栈负责。

# 2. 本地方法栈的特性

本地方法栈具有以下关键特性,与虚拟机栈非常相似:

  1. 线程私有 (Thread-Private):与虚拟机栈一样,本地方法栈也是线程私有的。每个线程在创建时,如果 JVM 支持并需要本地方法栈,就会为其分配一个独立的本地方法栈。其生命周期与线程绑定,随线程创建而创建,随线程结束而销毁。

  2. 内存大小可配置 (Fixed or Dynamic Size):

    • 《Java虚拟机规范》允许本地方法栈的实现是固定大小的,也可以是可动态扩展的。具体的实现策略由 JVM 厂商决定。
  3. 可能发生的异常 (Errors):本地方法栈在内存溢出方面的行为与虚拟机栈一致:

    • StackOverflowError:如果本地方法栈的大小是固定的,当一个线程请求的栈深度(通常是本地方法的嵌套调用深度)超过了其允许的最大容量时,Java 虚拟机将抛出 StackOverflowError。
    • OutOfMemoryError:
      • 如果本地方法栈允许动态扩展,在尝试扩展栈容量时无法申请到足够的内存,JVM 将抛出 OutOfMemoryError。
      • 如果在创建新线程时,没有足够的内存来为其创建所需的本地方法栈,JVM 也会抛出 OutOfMemoryError。

# 3. 本地方法栈与本地方法的执行

本地方法通常是使用 C 或 C++ 等非 Java 语言实现的。本地方法栈在执行本地方法调用时的角色如下:

  1. 登记与加载:当一个 Java 线程调用一个本地方法时,它首先需要在本地方法栈中登记这个 native 方法的相关信息。然后,执行引擎 (Execution Engine) 在执行时会负责加载并链接到包含该本地方法实现的本地方法库 (Native Library)(通常是 .dll 或 .so 文件)。

本地方法栈、执行引擎与本地方法库的关系

  1. 进入非 JVM 世界:一旦调用了本地方法,线程就进入了一个全新的、不再受 JVM 严格管控的世界。本地方法的执行是直接在底层操作系统上运行本地机器码,而不是执行 JVM 字节码。

  2. 强大的权限与交互能力:在本地方法内部,代码拥有与 JVM 进程本身几乎相同的权限。它可以:

    • 通过 Java 本地接口 (JNI - Java Native Interface) 回调或访问 JVM 内部的运行时数据区(如创建 Java 对象、访问 Java 字段、调用 Java 方法等)。
    • 直接使用本地处理器(CPU)的寄存器。
    • 直接从本地内存堆 (Native Heap) 中分配任意数量的内存(需要开发者手动管理)。

# 4. JVM 规范与实现差异

《Java虚拟机规范》并未对本地方法栈的具体实现做出强制性规定,例如:

  • 使用语言:没有规定本地方法栈必须使用哪种语言实现。
  • 数据结构:没有规定其内部必须采用何种数据结构。
  • 是否必需:规范甚至允许 JVM 实现不支持 native 方法。如果一个 JVM 产品选择不支持本地方法,那么它也可以不实现本地方法栈。

# 5. HotSpot 虚拟机的实现

在目前最主流的 HotSpot Java 虚拟机中,其设计者做了一个简化的选择:它直接将本地方法栈和 Java 虚拟机栈合二为一了。

这意味着在 HotSpot JVM 中:

  • 不存在一个独立的物理“本地方法栈”内存区域。
  • 无论是 Java 方法的调用还是 Native 方法的调用,都使用同一个栈进行管理。
  • 因此,HotSpot JVM 的 -Xss 参数同时控制了 Java 方法调用栈帧和 Native 方法调用栈帧所能使用的总栈空间大小。栈溢出错误 (StackOverflowError) 也都在这同一个栈上发生。

合并的原因可能包括:

  • 简化 JVM 内部设计和实现。
  • 避免为两种栈分别管理内存带来的复杂性。
  • 在某些情况下,方法调用(无论是 Java 还是 Native)共享同一个栈可能更高效。

核心总结

  1. 功能:本地方法栈专门用于管理本地方法 (Native Method) 的调用。
  2. 特性:线程私有,大小可固定或动态扩展,可能抛出 StackOverflowError 或 OutOfMemoryError。
  3. 执行流程:调用 Native 方法时,在本地方法栈登记,执行引擎加载本地库并执行,执行期间可使用 JNI 与 JVM 交互。
  4. 规范灵活性:JVM 规范对本地方法栈无强制实现要求。
  5. HotSpot 实现:将本地方法栈与 Java 虚拟机栈合并为一个栈进行管理。
编辑此页 (opens new window)
上次更新: 2025/04/05, 20:16:54
JVM - 本地方法接口
JVM - 堆 (Heap)

← JVM - 本地方法接口 JVM - 堆 (Heap)→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式