欢迎访问昆山宝 鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理

新闻资讯

MENU

当前位置 : > >
软件开发知识

堆外内存之 图纸加密 DirectByteBuffer 详解

点击: 次  来源:宝鼎软件 时间:2017-08-20

原文出处: tomas家的小拨浪鼓

堆外内存

堆外内 存是相对付堆内内存的一个观念。堆内内存是由JVM所管控的Java历程内存,我们平时在Java中建设 的工具都处于堆内内存中,劳务派遣管理系统,而且它们遵循JVM的内存打点机制,JVM会回收 垃圾接纳机制统一打点它们的内存。那么堆 外内存就是存在于JVM管控之 外的一块内存区域,因此它是不受JVM的管控。

在讲授DirectByteBuffer之前,需要先 简朴相识两个常识点。

java引用范例,因为DirectByteBuffer是通过虚引用(Phantom Reference)来实现 堆外内存的释放的。

PhantomReference 是所有“弱引用”中最弱的引用范例。差异于 软引用和弱引用,虚引用无法通过 get() 要领来 取得方针工具的强引用从而利用方针工具,调查源码可以发明 get() 被重写为永远返回 null。

那虚引 用到底有什么浸染?其实虚 引用主要被用来 跟踪工 具被垃圾接纳的状态,通过查 察引用行列中是否包括工具所对应的虚引用来判定它是否 即将被垃圾接纳,从而采纳动作。它并不 被等候用来取得方针工具的引用,而方针工具被接纳前,它的引 用会被放入一个 ReferenceQueue 工具中,从而到 达跟踪工具垃圾接纳的浸染。

关于java引用范 例的实现和道理可以阅读之前的文章Reference 、ReferenceQueue 详解 和 Java 引用范例简述。

关于linux的内核态和用户态

堆外内存之  图纸加密 DirectByteBuffer 详解

  • 内核态:节制计 较机的硬件资源,并提供 上层应用措施运行的情况。好比socket I/0操纵可 能文件的读写操纵等
  • 用户态:上层应 用措施的勾当空间,应用措 施的执行必需依托于内核提供的资源。
  • 系统挪用:为了使 上层应用可以或许会见到这些资源,内核为 上层应用提供会见的接口。
  • 堆外内存之  图纸加密 DirectByteBuffer 详解

    因此我 们可以得知当我们通过JNI挪用的native要领实 际上就是从用户态切换到了内核态的一种方法。而且通 过该系统挪用利用操纵系统所提供的成果。

    Q:为什么需要用户历程(位于用户态中)要通过系统挪用(Java中纵然JNI)来挪用 内核态中的资源,可能说 挪用操纵系统的处事了?
    A:intel cpu提供Ring0-Ring3四种级此外运行模式,Ring0级别最高,Ring3最低。Linux利用了Ring3级别运行用户态,Ring0作为内核态。Ring3状态不能会见Ring0的地点空间,包罗代码和数据。因此用 户态是没有权限去操纵内核态的资源的,它只能 通过系统挪用外完成用户态到内核态的切换,然后在 完成相关操纵后再有内核态切换回用户态。

    DirectByteBuffer ———— 直接缓冲

    DirectByteBuffer是Java用于实 现堆外内存的一个重要类,我们可 以通过该类实现堆外内存的建设、利用和销毁。

    堆外内存之  图纸加密 DirectByteBuffer 详解

    DirectByteBuffer该类自己照旧位于Java内存模子的堆中。堆内内存是JVM可以直经受控、哄骗。

    而DirectByteBuffer中的unsafe.allocateMemory(size);是个一个native要领,这个要 领分派的是堆外内存,通过C的malloc来举办分派的。分派的 内存是系统当地的内存,并不在Java的内存中,也不属于JVM管控范畴,所以在DirectByteBuffer必然会 存在某种方法来哄骗堆外内存。

    在DirectByteBuffer的父类Buffer中有个address属性:

        // Used only by direct buffers
        // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
        long address;

    address只会被 直接缓存给利用到。之所以将address属性进级放在Buffer中,是为了在JNI挪用GetDirectBufferAddress时晋升它挪用的速率。
    address暗示分 派的堆外内存的地点。

    堆外内存之  图纸加密 DirectByteBuffer 详解

    unsafe.allocateMemory(size);分派完 堆外内存后就会返回分派的堆外内存基地点,并将这 个地点赋值给了address属性。这样我们后头通过JNI对这个 堆外内存操纵时都是通过这个address来实现的了。

    在前面我们说过,在linux中内核 态的权限是最高的,那么在 内核态的场景下,操纵系 统是可以会见任何一个内存区域的,所以操 纵系统是可以会见到Java堆的这个内存区域的。

    Q:那为什 么操纵系统不直接会见Java堆内的内存区域了?
    A:这是因为JNI要了解 见的内存区域是一个已经确定了的内存区域地质,那么该 内存地点指向的是Java堆内内存的话,那么假 如在操纵系统正在会见这个内存地点的时候,Java在这个时候举办了GC操纵,而GC操纵会 涉及到数据的移动操纵[GC常常会 举办先符号在压缩的操纵。即,将可接 纳的空间做符号,然后清 空符号位置的内存,然后会举办一个压缩,压缩就 会涉及到工具的移动,移动的 目标是为了腾出一块越发完整、持续的内存空间,以容纳更大的新工具],数据的移动会使JNI挪用的数据错杂。所以JNI挪用的 内存是不能举办GC操纵的。

    友情链接:    彩客网   K8彩苹果APP下载   微信买彩票合法吗   澳门彩票app网址   大乐透开奖直播