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

JVM 堆外内存详解

Java 进程内存占用除了JVM 运行时数据区,还有直接内存(Direct Memory)区域及 JVM 程序自身也会占用内存

  • 直接内存(Direct Memory)区域:直接内存通过使用Native堆外内存来存储数据,这意味着数据不会被JVM的垃圾回收机制自动回收。与JVM堆内存相比,直接内存的分配和释放成本较高,因为它涉及与操作系统交互和内存管理的开销,也可能导致OOM异常出现
  • JVM 程序自身:JVM本身是个本地程序,还需要其他的内存去完成各种基本任务,比如,JIT Compiler 在运行时对热点方法进行编译,就会将编译后的方法储存在 Code Cache 里面;GC 等功能需要运行在本地线程之中,类似部分都需要占用内存空间

Java 进程内存占用

JVM内存区域划分详见 Java 内存区域与内存溢出异常

堆外内存

JVM 的堆外内存是指分配在JVM堆之外的内存空间,它不受JVM的垃圾回收机制管理。 以下是几种常见的JVM堆外内存:

  1. 直接字节缓冲区(Direct ByteBuffers):Direct ByteBuffer是JVM堆外内存的一种形式,它通过使用Native堆外内存来存储数据。
  2. NIO(New I/O)内存映射文件(Memory-mapped Files):NIO提供了一种将文件映射到内存的方式,这种内存映射文件将文件的内容直接映射到堆外内存中,可以通过内存访问的方式来读写文件。
  3. JNI(Java Native Interface):JNI允许Java程序与本地代码进行交互,可以在本地代码中分配和管理堆外内存。

堆外内存可以使用Native Memory Tracking 或 Arthas memory 进行监控及诊断

直接字节缓冲区

在实际使用中,Java 会尽量对 Direct Buffer 仅做本地 IO 操作,对于很多大数据量的 IO 密集操作,可能会带来非常大的性能优势,因为:

  • Direct Buffer 可以通过ByteBuffer.allocateDirect()方法来创建,它的数据存储在堆外内存中,生命周期内内存地址都不会再发生更改,进而内核可以安全地对其进行访问,很多 IO 操作会很高效
  • 减少了堆内对象存储的可能额外维护工作,所以访问效率可能有所提高

Direct Buffer 创建和销毁过程中,都会比一般的堆内 Buffer 增加部分开销,所以通常都建议用于长期使用、数据较大的场景。

可以使用JVM参数设定直接内存限制

-XX:MaxDirectMemorySize=512M

大多数垃圾收集过程中,都不会主动收集 Direct Buffer,它的垃圾收集过程,就是基于 Cleaner(一个内部实现)和幻象引用(PhantomReference)机制,其本身不是 public 类型,内部实现了一个 Deallocator 负责销毁的逻辑。对它的销毁往往要拖到full GC的时候,所以使用不当很容易导致OutOfMemoryError

Direct Buffer 回收方式:

  • 在应用程序中,显式地调用System.gc()来强制触发。
  • 另外一种思路是,在大量使用 Direct Buffer 的部分框架中,框架会自己在程序中调用释放方法(Netty 就是这么做的,有兴趣可以参考其实现PlatformDependent0)
  • 重复使用 Direct Buffer

NIO

Java NIO(New I/O)是Java提供的一套用于高效处理I/O操作的API,引入自JDK 1.4版本。相对于传统的Java I/O(IO流)API,Java NIO提供了更灵活、更高效的非阻塞I/O操作方式,适用于构建高性能的网络应用程序。

Java NIO的核心概念包括以下几个部分:

  • 通道(Channel):通道是数据源和数据目标之间的连接,可以通过通道读取和写入数据。通道可以是双向的,可以从通道中读取数据,也可以向通道中写入数据
  • 缓冲区(Buffer):缓冲区是一个固定大小的数据容器,用于存储读取和写入的数据。通过缓冲区可以更高效地读写数据,避免频繁的数据拷贝操作。缓冲区可以读取和写入不同类型的数据,如字节、字符、整数等
  • 选择器(Selector):选择器是用于多路复用非阻塞I/O操作的组件。可以通过选择器同时管理多个通道,使得单线程可以处理多个通道的I/O操作,提高系统的性能和吞吐量

NIO提供了一种将文件映射到内存的方式,这种内存映射文件将文件的内容直接映射到堆外内存中。这种方式在处理大型文件时可以提供更高的性能和效率

JNI

使用JNI(Java Native Interface)可以在Java程序中通过调用本地代码来使用JVM堆外内存。JNI提供了一种机制,使得Java程序可以与本地代码进行交互,调用本地代码中的函数和访问本地内存

通过JNI,Java程序可以直接访问和操作本地内存,例如在C或C++中使用malloc()free()函数进行内存分配和释放

JNI操作JVM堆外内存具体步骤
  1. 定义本地方法:在Java类中声明本地方法,使用native关键字标记。
public class NativeMemoryExample {public native void allocateMemory(int size);public native void freeMemory();
}
  1. 生成本地方法的头文件:使用Java的javac命令编译Java源文件,然后使用javah命令生成本地方法的头文件。
javac NativeMemoryExample.java
javah NativeMemoryExample

这将生成名为NativeMemoryExample.h的头文件

  1. 实现本地方法:在本地代码中实现Java类中声明的本地方法。在本地方法中可以使用C/C++等编程语言来操作堆外内存
#include "NativeMemoryExample.h"
#include <stdlib.h>JNIEXPORT void JNICALL Java_NativeMemoryExample_allocateMemory(JNIEnv *env, jobject obj, jint size) {void *buffer = malloc(size);// 使用buffer进行堆外内存操作
}JNIEXPORT void JNICALL Java_NativeMemoryExample_freeMemory(JNIEnv *env, jobject obj) {// 释放之前分配的堆外内存free(buffer);
}
  1. 编译本地代码:使用C/C++编译器将本地代码编译为共享库(或动态链接库)
gcc -shared -fpic -o libNativeMemoryExample.so NativeMemoryExample.c
  1. 加载本地库:在Java程序中使用System.loadLibrary()方法加载本地库
public class Main {static {System.loadLibrary("NativeMemoryExample");}public static void main(String[] args) {NativeMemoryExample example = new NativeMemoryExample();example.allocateMemory(1024);  // 调用本地方法分配堆外内存// ...example.freeMemory();  // 调用本地方法释放堆外内存}
}

通过以上步骤,Java程序可以使用JNI调用本地方法,在本地代码中进行对JVM堆外内存的分配和释放操作。需要注意的是,在使用JNI时应谨慎管理内存,避免内存泄漏和溢出,确保正确地释放分配的堆外内存


参考资料:

  1. Java Native Interface
  2. Direct Buffer
  3. Native Memory Tracking

相关文章:

JVM 堆外内存详解

Java 进程内存占用除了JVM 运行时数据区&#xff0c;还有直接内存&#xff08;Direct Memory&#xff09;区域及 JVM 程序自身也会占用内存 直接内存&#xff08;Direct Memory&#xff09;区域&#xff1a;直接内存通过使用Native堆外内存来存储数据&#xff0c;这意味着数据…...

数据库的基本概念以及MySQL基本操作

一、数据库的基本概念 1、数据库的组成 数据&#xff1a;描述事物的符号记录 包括数字&#xff0c;文字、图形、图像、声音、档案记录等 以“记录”形式按统一格式进行存储 表&#xff1a;将不同的记录组织在一起&#xff0c;用来存储具体数据 数据库&#xff1a; 表的集合…...

【Docker】Docker安装Nginx配置静态资源

1.下载镜像 2.创建nginx配置文件 3.创建nginx容器运行 4.配置nginx静态资源 1.下载镜像 Dockerhub官网&#xff1a;Docker docker pull nginx docker pull nginx下载最新版本 默认latest 下载指定版本docker pull nginx:xxx 2.创建nginx配置文件 启动容器之前要创建nginx…...

【码神之路】【Golang】博客网站的搭建【学习笔记整理 持续更新...】

介绍 一个用原生GO开发的博客网站&#xff0c;涉及Golang Web开发、Web服务器搭建和HTTP请求处理、模板与静态资源处理等 技术栈 后端&#xff1a;Go、Go并发机制前端&#xff1a;HTML模版链接直达 Golang搭建博客网站的学习视频 注&#xff1a;这里我只记录我实质✅学习到…...

Win10 电源选项那选择“关闭显示器“为1分钟,1分钟后就锁屏了?怎么才能关闭显示器后不锁屏

环境&#xff1a; Win10专业版 问题描述&#xff1a; Win10 电源选项那选择"关闭显示器"为1分钟&#xff0c;1分钟后就锁屏了&#xff1f;怎么才能关闭显示器后不锁屏 解决方案&#xff1a; 方法一 更改注册表可以实现关闭显示器而不锁屏的效果。请按照以下步骤…...

虚拟机centos设置网络模式(桥接|NAT)

前言 桥接模式是通过物理网卡直接与外部网络建立联系的&#xff0c;而NAT模式则是通过虚拟网卡VMnet1或VMnet8通过宿主机共享IP与外部建立网络关系当需要将虚拟机资源共享给局域网用户使用时&#xff0c;宜采用桥接模式&#xff1b;当需要保护虚拟机资源&#xff0c;确保只能由…...

MySQL 8.2 Command Line Client打开时一闪而过闪退问题

MySQL8.2安装成功后&#xff0c;发现打开MySQL 8.0 Command Line Client时出现一闪而过&#xff0c;打不开的情况。 解决方案&#xff1a; 1、打开MySQL 8.2 Command Line Client文件位置 2、右键选择属性 3、复制它的目标 4、我复制下来的目标路径是这样的&#xff0c;"…...

【NI-RIO入门】CompactRIO介绍及环境安装

CompactRIO是什么&#xff1f; CompactRIO系统提供了高处理性能、传感器专用I/O和紧密集成的软件工具&#xff0c;使其成为工业物联网、监测和控制应用的理想之选。实时处理器提供可靠&#xff0c;可预测的行为&#xff0c;而FPGA在需要高速逻辑和精确定时的较小任务上表现出色…...

生产问题 Recv-Q101

生产上服务端口 Recv-Q101 新请求到服务器的失败&#xff0c;幸好及时发现&#xff0c;通过重启服务之后得到解决&#xff0c;具体原因等待排查 目前觉得的原因是&#xff1a;某些请求暂用时间比较久...

从零开始:Rust环境搭建指南

大家好&#xff01;我是lincyang。 今天&#xff0c;我们将一起探讨如何从零开始搭建Rust开发环境。 Rust环境搭建概览 Rust是一种系统编程语言&#xff0c;以其安全性、并发性和性能闻名。搭建Rust环境是学习和使用这一语言的第一步。 第一步&#xff1a;安装Rust Rust的…...

Tensorrt 实现 yolov5-cls 遇到的问题

yolov5-6.2增加了分类训练、验证、预测和导出&#xff08;所有 11 种格式&#xff09;&#xff0c;还提供了 ImageNet 预训练的 YOLOv5m-cls、ResNet&#xff08;18、34、50、101) 和 EfficientNet (b0-b3) 模型. 官方Git : https://github.com/ultralytics/yolov5 分类模型与…...

智能指针(Newbie Note)

智能指针专题 1.普通指针的问题2.智能指针是什么什么是所有权 3.智能指针三个好处&#xff1a;4.C11提供的智能指针4.1 shared_ptr&#xff08;共享所有权指针&#xff09;4.1.1 分配内存4.1.2 成员函数4.1.3 计数情况汇总&#xff1a;4.1.4 示例代码(计数)4.1.5 示例代码(rese…...

2023.11.22 homework

七年级数学 五年级数学 也不知道可以教到几年级&#xff0c;估计很快就教不动了。人生啊。...

存储日志数据并满足安全要求

日志数据是包含有关网络中发生的事件的记录的重要信息&#xff0c;日志数据对于监控网络和了解网络活动、用户操作及其动机至关重要。 由于网络中的每个设备都会生成日志&#xff0c;因此收集的数据量巨大&#xff0c;管理和存储所有这些数据成为一项挑战&#xff0c;日志归档…...

Linux系统管理与服务器安全:构建稳健云数据中心

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在当今数字化时代&#xff0c;云数据中心已经成…...

用css实现原生form中radio单选框和input输入框的hover样式以及聚焦focus的样式

一.问题描述&#xff1a;用css实现原生form中radio单选框和input的hover已经focus的样式 在实际的开发中&#xff0c;一般公司ui都会给效果图&#xff0c;比如单选按钮radio样式&#xff0c;input输入框hover的时候样式&#xff0c;以及focus的时候样式&#xff0c;等等&#…...

【中国平安社招校招】【内推】【当天内推】

中国平安社招校招内推 通过内推链接即时内推&#xff0c;反馈速度比正常要快(可私信问进度) 开放大量HC(不限岗位和地区,技术、设计、产品、运营、数据等都可内推) Step1&#xff1a;查看相关职位 浏览平安的招聘官网&#xff1a;复制以下地址至浏览器打开。注意以下链接包含…...

CentOS 8最小安装,VM使用这个内存占用小很多

文章目录 一、安装包下载作者使用的安装包 二、安装过程截图三、最小化安装拥有的外部命令四、查看ip&#xff08;方便ssh连接&#xff09;五、yum源有问题参考文档 一、安装包下载 CentOS 网站&#xff1a; https://www.centos.org/CentOS 维基&#xff1a; https://wiki.cen…...

【C++ Primer Plus学习记录】递增运算符(++)和递减运算符(--)

递增运算符&#xff08;&#xff09;和递减运算符&#xff08;--&#xff09;&#xff1a;前缀版本位于操作数前面&#xff0c;如x&#xff1b;后缀版本位于操作数后面&#xff0c;如x。两个版本对操作数的影响是一样的&#xff0c;但是影响的时间不同。这就像吃饭前买单和吃饭…...

Oracle 数据库中 查询时如何使用日期(时间)作为查询条件

在 Oracle 数据库中&#xff0c;可以使用日期&#xff08;时间&#xff09;作为查询条件来筛选数据。 格式化日期的三种方式 方式一: 关键字 DATE 使用关键字DATE&#xff0c; 仅表示日期类型&#xff0c;并不包含时间信息 方式二&#xff1a;关键字TIMESTAMP 使用关键字TI…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...