当前位置:网站首页>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程序进程所占的内存空间 = 本地内存 + 堆空间

边栏推荐
- 支付流程如何测试?
- The project connects with Alipay payment, and the intranet penetration realizes the monitoring of asynchronous callback notification of successful payment of Alipay
- Approval of meeting OA
- Acticiti中startProcessInstanceByKey方法在variable表中的如何存储
- 一道数学题,让芯片巨头亏了5亿美金
- How does the TCP server handle multiple client connections on one port (one-to-one or one to many)
- 【牛客讨论区】第七章:构建安全高效的企业服务
- Complete Binary Tree
- Use of file i/o in C
- 柔性数组以及常见问题
猜你喜欢

使用mq消息队列来进行下单流程的高并发设计,消息挤压,消息丢失,消息重复的产生场景和解决方案

JVM上篇:内存与垃圾回收篇十四--垃圾回收器

SVN使用详解

Plato farm is expected to further expand its ecosystem through elephant swap

35.滚动 scroll

集成开发环境Pycharm的安装及模板设置

R-score reproduction R-Precision evaluation index quantitative text generation image r-score quantitative experiment whole process reproduction (R-Precision) quantitative evaluation experiment step on

Mysql表的约束

strlen和sizeof的区别

Advantages of smart exhibition hall design and applicable industry analysis
随机推荐
Sunset red warm tone tinting filter LUTS preset sunset LUTS 1
How to copy Photoshop layers to other documents
The execution process of a select statement in MySQL
对话框简介
一道数学题,让芯片巨头亏了5亿美金
"Photoshop2021 introductory tutorial" flatten "perspective images
Affine transformation module and conditional batch Standardization (CBN) of detailed text generated images
How to test the payment process?
《Robust and Precise Vehicle Localization based on Multi-sensor Fusionin Diverse City Scenes》翻译
QT 菜单栏、工具栏和状态栏
集合框架的使用
How to sinicize the JMeter interface?
Invert a Binary Tree
节流函数的demo——正则表达式匹配
"Photoshop2021 tutorial" adjust the picture to different aspect ratio
There is no need to install CUDA and cudnn manually. You can install tensorflow GPU through a one-line program. Take tensorflow gpu2.0.0, cuda10.0, cudnn7.6.5 as examples
Test basis 5
微淼联合创始人孙延芳:以合规为第一要义,做财商教育“正规军”
会议OA之我的审批
二、MySQL高级