当前位置:网站首页>JVM上篇:内存与垃圾回收篇十--运行时数据区-直接内存
JVM上篇:内存与垃圾回收篇十--运行时数据区-直接内存
2022-07-27 05:01:00 【_院长大人_】
JVM上篇:内存与垃圾回收篇十–运行时数据区-直接内存
直接内存不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。
直接内存是在Java堆外的、直接向系统申请的内存区间。
来源于NIO,通过存在堆中的DirectByteBuffer操作Native内存
public static ByteBuffer allocateDirect(int capacity) { return new DirectByteBuffer(capacity); }通常,访问直接内存的速度会优于Java堆。即读写性能高。
- 因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。
- Java的NIO库允许Java程序使用直接内存,用于数据缓冲区
1. 查看直接内存的占用与释放
代码示例
/** * IO NIO (New IO / Non-Blocking IO):非阻塞式 * byte[] / char[] Buffer * Stream Channel * * 查看直接内存的占用与释放 */
public class BufferTest {
private static final int BUFFER = 1024 * 1024 * 1024;//1GB
public static void main(String[] args){
//直接分配本地内存空间
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
System.out.println("直接内存分配完毕,请求指示!");
Scanner scanner = new Scanner(System.in);
scanner.next();
System.out.println("直接内存开始释放!");
byteBuffer = null;
System.gc();
scanner.next();
}
}
未启动程序时内存时的任务管理器

启动程序后分配了1g的直接内存的任务管理器
查看进程id


释放掉1g直接内存的任务管理器

程序关闭后的任务管理器

2. 非直接缓存与直接缓存
2.1 非直接缓存(BIO)
原来采用BIO的架构,在读写本地文件时,我们需要从用户态切换成内核态

2.2 直接缓存(NIO)
使用NIO时,如下图。操作系统划出的直接缓存区可以被Java代码直接访问,只有一份。NIO适合对大文件的读写操作

3. 使用本地内存读写数据的测试

测试代码
package com.atguigu.java;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class BufferTest1 {
private static final String TO = "C:\\Users\\eric\\Desktop\\test\\IOTest\\u盘备份.rar";
private static final int _100Mb = 1024 * 1024 * 100;
public static void main(String[] args) {
long sum = 0;
String src = "C:\\Users\\eric\\Desktop\\test\\IOTest\\u盘备份.rar";
for (int i = 0; i < 3; i++) {
String dest = "C:\\Users\\eric\\Desktop\\test\\IOTest\\u盘备份-"+i+".rar";
sum += io(src,dest);//54606
// sum += directBuffer(src,dest);//50244
}
System.out.println("总花费的时间为:" + sum );
}
private static long directBuffer(String src,String dest) {
long start = System.currentTimeMillis();
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
inChannel = new FileInputStream(src).getChannel();
outChannel = new FileOutputStream(dest).getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_100Mb);
while (inChannel.read(byteBuffer) != -1) {
byteBuffer.flip();//修改为读数据模式
outChannel.write(byteBuffer);
byteBuffer.clear();//清空
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inChannel != null) {
try {
inChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outChannel != null) {
try {
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
return end - start;
}
private static long io(String src,String dest) {
long start = System.currentTimeMillis();
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(src);
fos = new FileOutputStream(dest);
byte[] buffer = new byte[_100Mb];
while (true) {
int len = fis.read(buffer);
if (len == -1) {
break;
}
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
return end - start;
}
}
未使用本地内存

使用本地内存

结论:使用本地内存读写会快一些
4 直接内存OOM
- 直接内存也可能导致
OutofMemoryError异常 - 由于直接内存在Java堆外,因此它的大小不会直接受限于
-Xmx指定的最大堆大小,但是系统内存是有限的,Java堆和直接内存的总和依然受限于操作系统能给出的最大内存 - 直接内存的
缺点为:- 分配回收成本较高
- 不受JVM内存回收管理
- 直接内存大小可以通过
MaxDirectMemorySize设置 - 如果不指定,默认与堆的最大值-Xmx参数值一致
代码示例
/** * 本地内存的OOM: OutOfMemoryError: Direct buffer memory */
public class BufferTest2 {
private static final int BUFFER = 1024 * 1024 * 20;//20MB
public static void main(String[] args) {
ArrayList<ByteBuffer> list = new ArrayList<>();
int count = 0;
try {
while(true){
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
list.add(byteBuffer);
count++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
System.out.println(count);
}
}
}

4.1 ByteBuffer.allocateDirect(BUFFER)源码
ByteBuffer.allocateDirect(BUFFER)本质上是unsafe.allocateMemory(size)

4.2 直接通过 Unsafe 类申请本地内存
代码示例
/** * -Xmx20m -XX:MaxDirectMemorySize=10m */
public class MaxDirectMemorySizeTest {
private static final long _1MB = 1024 * 1024;
public static void main(String[] args) throws IllegalAccessException {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
while(true){
unsafe.allocateMemory(_1MB);
}
}
}
设置设置JVM 参数
-Xmx20m -XX:MaxDirectMemorySize=10m抛出 OOM 异常

5. JDK7与JDK8的JVM内存结构
可以理解Java程序进程所占的内存空间 = 本地内存 + 堆空间

边栏推荐
- How does the TCP server handle multiple client connections on one port (one-to-one or one to many)
- C language address book management system (linked list, segmented storage of mobile phone numbers, TXT file access, complete source code)
- How does PS import LUT presets? Photoshop import LUT color preset tutorial
- Flexible array and common problems
- Installation and template setting of integrated development environment pychar
- Could not autowire.No beans of ‘userMapper‘ type found.
- 一、MySQL基础
- Error: cannot read properties of undefined (reading 'then')
- 【无标题】按照一定的条件,对 i 进行循环累加。条件通常为循环数组的长度,当超过长度就停止循环。因为对象无法判断长度,所以通常搭配 Object.keys() 使用。\nforEach 一般认为是 普
- Slashes / and backslashes involved in writing code\
猜你喜欢

Inspiration from "flying man" Jordan! Another "arena" opened by O'Neill

Could not autowire.No beans of ‘userMapper‘ type found.

【搜索】DFS之连通性模型 + 搜索顺序

C language address book management system (linked list, segmented storage of mobile phone numbers, TXT file access, complete source code)

使用ngrok做内网穿透

来自“飞人”乔丹的启示!奥尼尔开启的另一个“赛场”

Final Cut Pro Chinese tutorial (2) understanding of material window

Select user stories | the false positive rate of hole state in jushuitan is almost 0. How to do this?

Introduction to MySQL optimization

【Acwing】第61场周赛 题解
随机推荐
使用ngrok做内网穿透
Acticiti中startProcessInstanceByKey方法在variable表中的如何存储
Svn usage details
OFDM 16 lecture 2-ofdm and the DFT
【搜索】DFS之连通性模型 + 搜索顺序
JVM上篇:内存与垃圾回收篇十四--垃圾回收器
Typescript details
Reproduce ssa-gan using the nine day deep learning platform
Invert a Binary Tree
Use of file i/o in C
Why is select not recommended*
How to test the payment process?
"Photoshop2021 tutorial" align and distribute to make dot patterns
事件的接受与忽略
How does the TCP server handle multiple client connections on one port (one-to-one or one to many)
Plato Farm有望通过Elephant Swap,进一步向外拓展生态
抽卡程序模拟
智慧展厅设计的优势及适用行业分析
Event Summary - common summary
Solution and principle analysis of feign call missing request header