# JVM
- 直接内存
JDK
版本:1.8
# 1、直接内存(Direct Memory
)
直接内存(Direct Memory
)并不是虚拟机运行时数据区的一部分,也不是《Java
虚拟机规范》中定义的内存区域。但是这部分内存也会被频繁地使用,而且也会导致OutOfMemeory
异常。
在JDK 1.4
版本中引入了NIO
类,引入了一种基于通道(Channel
)于缓冲区(Buffer
)的I/O
方式,它可以直接调用Native
函数分配堆外内存空间,然后通过存储在堆中的DirectByteBuffer
对象作为这块空间的引用以此来对其进行操作。这样就避开了JVM
于操作系统之间的内存屏障,减少了在Java
堆与Native
堆中进行来回复制的额外开销,在某些场景中可以显著提高性能。同时访问直接内存的速度也会优于Java
堆,即读写性能高。
本机直接内存的分配是不会受到JVM
堆内存大小的限制,但是它还是会受到本机总内存(包括物理内存,SWAP
分区或者分页文件)的大小以及处理器寻址空间的限制。一般在配置虚拟机参数时,会根据实际内存设置-Xmx
等参数信息,但经常忽略掉直接内存,使得各个内存区域总和大于物理内存限制(包括物理和操作系统级的限制),从而导致动态进行扩展时出现OutOfMemory
异常。
也正是因为直接内存不是虚拟机运行时数据区的一部分,直接内存不受JVM
内存回收管理,所以其分配回收成本也较高。直接内存大小可通过MaxDirectMemorySize
选项进行配置,如果不进行指定默认与堆空间的-Xmx
参数值保持一致。
# 2、直接内存与非直接内存差异
使用非直接内存进行IO
读写文件时,需要与物理磁盘进行交互。在执行读写操作时,JVM
与OS
直接存在内存屏障,所以进行数据的交互时就会进行来回复制。换而言之就是需要由用户态切换到内核态,内核态中需要同时维护两份重复数据,这样带来的额外性能开销是非常大的。
如下为非直接内存JVM
与OS
之间的数据交互图:
使用直接内存进行IO
读写文件时,直接调用Native
函数分配堆外内存空间,并且这部分内存可以通过存储在堆中的DirectByteBuffer
对象对其进行操作,避免了内存屏障同时也只需要维护一份数据。避免了不必要的性能开销。
如下为直接内存JVM
与OS
之间的数据交互图:
GitHub源码地址:https://github.com/kapbc/Java-Kapcb/tree/master/src/main/java/com/kapcb/ccc/jvm
备注:此文为笔者学习
JVM
的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。
更多Java技术笔记可扫码关注下方微信公众号。
标签:Java,虚拟机,内存,JVM,直接,进行 来源: https://blog.csdn.net/qq_43911324/article/details/122760164
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。