概述
直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中农定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用native 函数库直接分配堆外内存,然后通脱一个存储在Java堆中的DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
-
本机直接内存的分配不会受到Java 堆大小的限制,受到本机总内存大小限制
-
配置虚拟机参数时,不要忽略直接内存 防止出现OutOfMemoryError异常
直接内存(堆外内存)与堆内存比较
- 直接内存申请空间耗费更高的性能,当频繁申请到一定量时尤为明显
- 直接内存IO读写的性能要优于普通的堆内存,在多次读写操作的情况下差异明显
package com.xnccs.cn.share; import java.nio.ByteBuffer; /** * 直接内存 与 堆内存的比较 */ public class ByteBufferCompare { public static void main(String[] args) { allocateCompare(); //分配比较 operateCompare(); //读写比较 } /** * 直接内存 和 堆内存的 分配空间比较 * * 结论: 在数据量提升时,直接内存相比非直接内的申请,有很严重的性能问题 * */ public static void allocateCompare(){ int time = 10000000; //操作次数 long st = System.currentTimeMillis(); for (int i = 0; i < time; i++) { //ByteBuffer.allocate(int capacity) 分配一个新的字节缓冲区。 ByteBuffer buffer = ByteBuffer.allocate(2); //非直接内存分配申请 } long et = System.currentTimeMillis(); System.out.println("在进行"+time+"次分配操作时,堆内存 分配耗时:" + (et-st) +"ms" ); long st_heap = System.currentTimeMillis(); for (int i = 0; i < time; i++) { //ByteBuffer.allocateDirect(int capacity) 分配新的直接字节缓冲区。 ByteBuffer buffer = ByteBuffer.allocateDirect(2); //直接内存分配申请 } long et_direct = System.currentTimeMillis(); System.out.println("在进行"+time+"次分配操作时,直接内存 分配耗时:" + (et_direct-st_heap) +"ms" ); } /** * 直接内存 和 堆内存的 读写性能比较 * * 结论:直接内存在直接的IO 操作上,在频繁的读写时 会有显著的性能提升 * */ public static void operateCompare(){ int time = 1000000000; ByteBuffer buffer = ByteBuffer.allocate(2*time); long st = System.currentTimeMillis(); for (int i = 0; i < time; i++) { // putChar(char value) 用来写入 char 值的相对 put 方法 buffer.putChar('a'); } buffer.flip(); for (int i = 0; i < time; i++) { buffer.getChar(); } long et = System.currentTimeMillis(); System.out.println("在进行"+time+"次读写操作时,非直接内存读写耗时:" + (et-st) +"ms"); ByteBuffer buffer_d = ByteBuffer.allocateDirect(2*time); long st_direct = System.currentTimeMillis(); for (int i = 0; i < time; i++) { // putChar(char value) 用来写入 char 值的相对 put 方法 buffer_d.putChar('a'); } buffer_d.flip(); for (int i = 0; i < time; i++) { buffer_d.getChar(); } long et_direct = System.currentTimeMillis(); System.out.println("在进行"+time+"次读写操作时,直接内存读写耗时:" + (et_direct - st_direct) +"ms"); } }
输出:
在进行10000000次分配操作时,堆内存 分配耗时:12ms
在进行10000000次分配操作时,直接内存 分配耗时:8233ms
在进行1000000000次读写操作时,非直接内存读写耗时:4055ms
在进行1000000000次读写操作时,直接内存读写耗时:745ms
可以自己设置不同的time 值进行比较
分析
从数据流的角度,来看
非直接内存作用链:
本地IO –>直接内存–>非直接内存–>直接内存–>本地IO
直接内存作用链:
本地IO–>直接内存–>本地IO
直接内存使用场景
- 有很大的数据需要存储,它的生命周期很长
- 适合频繁的IO操作,例如网络并发场景
java 直接内存回收
是通过GC回收的,不过GC只会在老年区满了触发Full GC时,才会去顺便清理直接内存的废弃对象
参考:
相关推荐
输出 GC 日志对于跟踪分析 GC 的状况,无疑是最明显和直接的分析内存回收状况的方 法,只是 GC 日志输出后需要人肉的进行分析,来判断 GC 的状况。 JVM 支持将日志输出到控制台或指定的文件中,方法为: 1、 输出到...
JVM内存管理,平时大家估计都不是很在意,一直到快跳槽了,快面试了,大家可能会看看,也可能直接忽略不计了。JVM内存管理是虚拟机的事情,和开发人员有什么关系。这种想法一直在我们开发人员的潜意识中存在:“内存...
资源描述: 1.JVM中[直接内存]的所有内容-pdf 2.资源内容:JVM中[直接内存]所有内容 3.学习目标:了解jvm底层原理 4.特点:简单易懂,容易上手 5.使用说明:需要使用pdf打开
JVM 内存区域JVM 内存区域JVM 运行时内存划分程序计数器Java虚拟机栈本地方法栈方法区运行时常量池直接内存HotSpot 虚拟机对象揭秘对象的创建对象
Direct-Cache 将缓存的值存储在不受 gc 管理的 jvm 直接内存(offheap)中,有了这个库,您可以缓存大量数据并且没有 gc 暂停问题。 Cache'key 仍在 jvm 堆中。 缓存值应该足够大(> 1k),所以直接缓存真的会有帮助...
第28讲 Java内存区域-直接内存和运行时常量池 00:15:53 第29讲 对象在内存中的布局-对象的创建 00:21:19 第30讲 探究对象的结构 00:13:47 第31讲 深入理解对象的访问定位 00:08:01 第32讲 垃圾回收-...
HotSpot的垃圾回收机制采用分代回收,堆分为年轻代和老年代,非堆...像NIO的直接文件内存读取,使用的是直接内存,只有出发了FullGC方能回收该区域!JNI调用本地库,本地代码所消耗的内存需要操作系统额外开辟内存。
彻底分析 StringTable的相关知识与性能优化,掌握直接内存分配原理和释放手段。 * 在垃圾回收章节,不仅会介绍垃圾回收算法、分代垃圾回收机制,还会重点介绍 G1 垃圾回收器,辨析 Full GC 发生条件,jdk8以来对垃圾...
cleakka, 在 sun.misc.Cleaner 和Akka上,集群内存缓存基于 Cleakka ( 清洗器 Akka ):是基于 sun.misc.Cleaner 和Akka的内存缓存使用JVM直接内存将缓存数据存储在堆内存中;这将减少GC延迟如果缓存条目被删除,则...
这样做可以防止外部直接访问对象的数据,而是通过对象提供的接口进行操作,从而提高了安全性和灵活性。 继承: 继承允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以扩展或修改从父类继承的行为,...
1.1 对象优先在Eden区分配 1.2 大对象直接进入老年代 1.3 长期存活的对象将进入老年代
1、JVM 内存分配图解的 Visio 工程图。 2、直接下载使用、可自行调整和修改
第28节Java内存区域-直接内存和运行时常量池00:15:53分钟 | 第29节对象在内存中的布局-对象的创建00:21:19分钟 | 第30节探究对象的结构00:13:47分钟 | 第31节深入理解对象的访问定位00:08:01分钟 | 第32节垃圾...
进程与线程 进程 :进程是程序的一次执行过程。...线程 :一个进程中包含多个线程,线程共享进程的堆和方法区的资源以及直接内存,同时线程私有资源的包括 程序计数器 、 虚拟机栈 和 本地方法栈 。
java代码-volatile的可见性 由于JVM运行的实体是线程...不能直接操作主内存中的变量 各个线程的工作内存中存储主内存中的变量副本拷贝 因此不同的线程之间无法访问对方的工作内存 线程间的通信必须通过主内存来完成
自己总结的jvm中直接内存的笔记,绘制了详细的思维导图,每个思维导图中均有详细的博文解释,方便大家学习和理解,免费分享给大家。适合jvm的爱好者和学习者
一、JVM 内存模型 JVM 的内存模型主要分为三个区:堆区、栈区和方法区。 * 堆区:用于存储初始化的对象,成员变量(非静态变量),所有的对象实例和数组都要在堆上分配。 * 栈区:栈的结构是栈帧组成的,调用一个...
读各类翻译的Java虚拟机原理,都被不如直接读官方的原版白皮书效果好。Java虚拟机,顾名思义,本质上是个虚拟的电脑,含有虚拟CPU、虚拟内存和虚拟操作系统的概念。JVM白皮书是对这个电脑的CPU结构指令集、操作系统...
JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)
想要下载此文件,请先下载本人“java程序中的内存分配问题”,因为那个例子比较简单而且分析详细透彻,可以使你更容易理解,如果你对java程序执行过程中的内存分配有一定的了解,可以直接下载本文件