首页 > 系统相关 >JVM内存布局与 JNA 调用本地方法原理详解

JVM内存布局与 JNA 调用本地方法原理详解

时间:2024-12-27 11:34:13浏览次数:2  
标签:Java 本地 JNA 详解 线程 内存 JVM 方法

JVM 内存布局详解

程序计数器(PC)

这个是当前线程正在执行的字节码行号指示器, 类似于实际的PC, 根据这里面的内存数据来确定程序接下来执行的指令. 在JAVA中, 每个线程都有一个, 相互隔离, 线程之间的切换就是基于程序计数器. 如果执行的是方法, 这里记录的是虚拟机字节码指令的地址. 注意:当执行的是Native方法的时候为空(Undefined).
因为只存储一个指令, 所以它不会出现任何 OutOfMemoryError.

Java虚拟机栈

每个线程私有, 里面装的多个栈帧, 每个栈帧对于的一个方法. 里面存储的是Java方法的内存模型. 相当于描述的是一个方法需要的内容. 逻辑上类似于操作系统中的进程栈, 每个线程都有一个虚拟机栈, 每个栈中都有多个栈帧. 每个方法的执行过程都是栈帧的进栈于出栈, 类似于进程中的函数调用.

每个栈帧存就是对方法的描述, 栈帧中存储局部变量, 局部变量是一个方法内使用的变量, 包括各种数据类型的临时变量. (boolean、byte、char、short、int、float、long、double 类型), 以及对象的引用. 对象本身并不会存储在线程栈中, 即使这个对象是在方法中新建的, 线程栈中也仅会保存对象的引用, 作为局部变量, 而对象本身则存储在JVM的堆空间中.

异常情况:线程请求的栈深度大于虚拟机允许的深度, 将抛出StackOverflowError异常. 如果虚拟机栈可以动态扩展, 当扩展的时候没有申请到内存的时候抛出OutOfMemoryError.

本地方法栈

每个线程都有自己的本地方法栈, 这时线程私有的, 用于线程支持对本地方法的调用, 本地方法栈(Native Method Stack)是为调用本地方法(Native Method)服务的, 一个典型的例子是使用 JNI(Java Native Interface)调用用 C/C++ 编写的本地代码. 本地方法通常用于调用操作系统的 API, 使用已有的 C++ 库, 与硬件交互等, 本地方法栈也就是本地方法代码执行的地方.

Java堆

Java虚拟机管理最大的一块,线程共享,存放对象实例和数组.分新生代(1/3)和老年代(2/3),新生代还可以分Eden(8/10)、From Survivor(1/10) 、To Survivor(1/10),是主要根据垃圾清理来分的.

异常情况: 无法再对对象实例分配, 并且堆也无法扩展时, 将抛出OutOfMemoryError.

方法区

线程共享, 主要存储被虚拟机加载的类信息, 常量, 静态变量, 即时编译器编译后的代码. 运行时常量池也是方法区的一部分, 比如String有一个常量池, 他就是放到这个里面的. 类似于进程的代码区以及全局变量区.

异常情况: 当方法区无法满足内存分配时, 将抛出OutOfMemoryError异常.

直接内存

NIO通过使用Native函数库直接分配对外内存, 因为JVM本质上是一个进程, 这部分内存实际上是 JVM 进程的堆内存, java 程序可以在内部申请这块内存使用, 这种使用方式相当于绕过了 JVM 的内存管理与自动回收机制, 内存管理需要开发者手动管理. Java 支持两种方法使用这块内存, 分别是 JVM 自身提供的接口, 这块内存直接被 Java 代码使用. 另一种是 Native 代码申请内存, 这部分内存用于 JNA 调用本地代码的时候使用. 这两种使用方式的相同点是, 两者均使用的是 JVM 这个进程的用户的虚拟空间的堆的内存空间, 不同点是:

特性 堆外内存(Off-Heap Memory) Native 代码申请的内存
分配方式 使用 JVM 提供的接口(如 Unsafe.allocateMemoryDirectByteBuffer). 通过本地代码(C/C++)直接调用操作系统 API(如 malloc).
管理接口 Java 层提供操作接口,UnsafeDirectByteBuffer 包装了分配的内存. 完全依赖 C/C++ 的内存管理工具(如指针操作).
语言依赖 完全在 Java 中操作,使用 Java 提供的工具类或方法来访问和管理内存. 必须通过 JNI 或其他桥接机制从 Java 调用 C/C++ 函数.
释放机制 DirectByteBuffer 可依赖 JVM 的 Cleaner 机制自动释放(但不及时). 由 C/C++ 开发者显式调用 freedelete 来释放内存.
线程安全性 Java 层可能提供一些线程安全特性(如 ByteBuffer 的读写同步). 完全依赖 C/C++ 代码的实现.
调试和诊断工具支持 JVM 提供了一些工具(如 jmap)可以查看堆外内存的使用情况. 必须依赖 C/C++ 的调试工具(如 valgrind).

异常情况: 不受Java堆大小限制, 但是受机器的物理内存限制, 当各个内存区域大于机器物理内存的时候, 会出现OutOfMemoryError.

标签:Java,本地,JNA,详解,线程,内存,JVM,方法
From: https://www.cnblogs.com/wevolf/p/18635212

相关文章

  • 171页PPT详解制造业采购供应链及财务管控业务流程蓝图规划
        本文详细阐述了甲方集团数字化转型采购供应链业务规划的核心内容。首先,通过全面的用户体验调研,识别业务能力提升的机会,为后续计划奠定基础。在采购物控的业务管理方面,提出了“低成本、高齐套”的材料供应愿景,旨在降本增效,提高库存周转,减少库存呆滞,提升生产供应及......
  • vue 中 keep-alive 详解
    一、定义与作用`keep-alive`是Vue.js提供的一个内置组件,用于缓存动态组件。当一个组件被包裹在`keep-alive`组件内部时,在组件切换过程中,该组件的状态(如组件中的数据、DOM状态等)会被保留,而不是像普通组件那样被销毁和重新创建。这对于提高应用性能和用户体验非常有用,特别是......
  • 高德地图API详解
    高德地图API是一款基于Web的服务,为开发者提供了丰富的地理数据服务和功能。以下是对高德地图API的详细介绍:一、主要功能地图显示:支持全球范围各地的地图显示,包括街道、建筑物、自然地理等,用户可以将高德地图以图片形式嵌入自己的网页或应用中。地理/逆地理编码:提供结构化......
  • RBAC 知识详解:核心要点、优势及各领域应用
    一、RBAC简介定义RBAC即基于角色的访问控制(Role-BasedAccessControl)。它是一种通过角色来管理用户对系统资源访问权限的访问控制模型。在RBAC模型中,权限与角色相关联,用户通过被分配适当的角色来获取相应的权限,从而访问系统中的资源。这种模型提供了一种将用户与权限解耦......
  • JVM实战—2.JVM内存设置与对象分配流转
    大纲1.JVM内存划分的原理细节2.对象在JVM内存中如何分配如何流转3.部署线上系统时如何设置JVM内存大小4.如何设置JVM堆内存大小5.如何设置JVM栈内存与永久代大小6.问题汇总 1.JVM内存划分的原理细节(1)背景引入(2)大部分对象的存活周期都是极短的(3)少数对象是长期存......
  • Linux系统和makefile详解
    ###Linux系统详解Linux是一个开源且功能强大的操作系统内核,自1991年由林纳斯·托瓦兹首次发布以来,它已经成为全球最流行的操作系统之一。Linux的核心特性包括开源、多用户多任务、高稳定性与安全性,以及良好的跨平台能力。1.**开源**:Linux的源代码对所有人开放,任何人都可以......
  • Java多线程处理文件详解与代码示例
    在Java编程中,文件处理是一项常见的任务。当需要处理大量文件或处理文件的时间较长时,单线程的处理方式可能会显得效率低下。为了提高文件处理的效率,我们可以使用多线程技术。本文将详细介绍如何使用Java多线程来处理文件,并提供一个详细的代码示例,该示例可以直接运行。一、多线程处......
  • html页面原生事件详解
    https://www.baidu.com/s?wd=html%E9%A1%B5%E9%9D%A2%E5%8E%9F%E7%94%9F%E4%BA%8B%E4%BB%B6%E8%AF%A6%E8%A7%A3&rsv_spt=1&rsv_iqid=0xa30412530022f729&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&rqlang=cn&tn=baiduhome_pg&rsv_dl=t......
  • 4. JVM 运行时内存
    Java堆从GC的角度还可以细分为:新生代(Eden区、FromSurvivor(S0)区和ToSurvivor区(S1))老年代1.新生代a)Eden区Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。b......
  • JVM内存模型、垃圾回收机制及简单调优方式
    JVM内存模型:1.方法区  用来存放类加载的信息,同时存放静态属性和方法(静态方法和普通方法)  jdk1.7之后,取消了方法区名称,改为元空间、方法区也叫元空间也叫永久区  方法区中的数据,可以被多线程共享。访问时会有数据共享的安全问题2.堆区  用来存放对象或数......