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

JVM内存区域划分详见 Java 内存区域与内存溢出异常
JVM 的堆外内存是指分配在JVM堆之外的内存空间,它不受JVM的垃圾回收机制管理。 以下是几种常见的JVM堆外内存:
堆外内存可以使用Native Memory Tracking 或 Arthas memory 进行监控及诊断
在实际使用中,Java 会尽量对 Direct Buffer 仅做本地 IO 操作,对于很多大数据量的 IO 密集操作,可能会带来非常大的性能优势,因为:
ByteBuffer.allocateDirect()方法来创建,它的数据存储在堆外内存中,生命周期内内存地址都不会再发生更改,进而内核可以安全地对其进行访问,很多 IO 操作会很高效Direct Buffer 创建和销毁过程中,都会比一般的堆内 Buffer 增加部分开销,所以通常都建议用于长期使用、数据较大的场景。
可以使用JVM参数设定直接内存限制
-XX:MaxDirectMemorySize=512M
大多数垃圾收集过程中,都不会主动收集 Direct Buffer,它的垃圾收集过程,就是基于 Cleaner(一个内部实现)和幻象引用(PhantomReference)机制,其本身不是 public 类型,内部实现了一个 Deallocator 负责销毁的逻辑。对它的销毁往往要拖到full GC的时候,所以使用不当很容易导致OutOfMemoryError
Direct Buffer 回收方式:
System.gc()来强制触发。Java NIO(New I/O)是Java提供的一套用于高效处理I/O操作的API,引入自JDK 1.4版本。相对于传统的Java I/O(IO流)API,Java NIO提供了更灵活、更高效的非阻塞I/O操作方式,适用于构建高性能的网络应用程序。
Java NIO的核心概念包括以下几个部分:
NIO提供了一种将文件映射到内存的方式,这种内存映射文件将文件的内容直接映射到堆外内存中。这种方式在处理大型文件时可以提供更高的性能和效率
使用JNI(Java Native Interface)可以在Java程序中通过调用本地代码来使用JVM堆外内存。JNI提供了一种机制,使得Java程序可以与本地代码进行交互,调用本地代码中的函数和访问本地内存
通过JNI,Java程序可以直接访问和操作本地内存,例如在C或C++中使用
malloc()和free()函数进行内存分配和释放
public class NativeMemoryExample {
public native void allocateMemory(int size);
public native void freeMemory();
}
javac NativeMemoryExample.java
javah NativeMemoryExample
这将生成名为NativeMemoryExample.h的头文件
#include "NativeMemoryExample.h"
#include
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);
}
gcc -shared -fpic -o libNativeMemoryExample.so NativeMemoryExample.c
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时应谨慎管理内存,避免内存泄漏和溢出,确保正确地释放分配的堆外内存
参考资料: