`

堆外内存

 
阅读更多

原文:http://lovestblog.cn/blog/2015/05/12/direct-buffer/

这里只截取自己要的

 

广义的堆外内存:新生代、老生代、持久代之外的内存,包括jvm本身在运行过程中分配的内存,jni里分配的内存,以及下面提到的DirectByteBuffer分配的内存等等

 

狭义的堆外内存:主要指java.nio.DirectByteBuffer在创建时分配的内存,本文也指的是狭义的堆外内存

 

System.gc

堆外内存不会对gc造成什么影响(System.gc除外),堆外内存的回收其实依赖于我们的gc机制。首先在java层面和这块堆外内存关联的只有与之关联的DirectByteBuffer对象,它记录了这块内存的基地址以及大小,gc能通过操作DirectByteBuffer对象来间接操作对应的堆外内存。

DirectByteBuffer对象在创建的时候关联了一个PhantomReference,PhantomReference是用于跟踪对象何时被回收的,它不能影响gc决策,但是gc过程中如果返现某个对象除了PhantomReference外没有其他地方引用,就会将这个引用java.lang.ref.Reference.pending队列里,在gc完毕时通知ReferenceHandler这个守护线程去执行一些后置处理,而DirectByteBuffer关联的PhantomReference是PhantomReference的一个子类,在最终处理里会通过Unsafe的free接口来释放DirectByteBuffer对应的对外内存块

JDK里ReferenceHandler实现:

private static class ReferenceHandler extends Thread {

        ReferenceHandler(ThreadGroup g, String name) {
            super(g, name);
        }

        public void run() {
            for (;;) {

                Reference r;
                synchronized (lock) {
                    if (pending != null) {
                        r = pending;
                        Reference rn = r.next;
                        pending = (rn == r) ? null : rn;
                        r.next = r;
                    } else {
                        try {
                            lock.wait();
                        } catch (InterruptedException x) { }
                        continue;
                    }
                }

                // Fast path for cleaners
                if (r instanceof Cleaner) {
                    ((Cleaner)r).clean();
                    continue;
                }

                ReferenceQueue q = r.queue;
                if (q != ReferenceQueue.NULL) q.enqueue(r);
            }
        }
    }

 

如果pending为空的时候,会通过lock.wait()一直等在那里,唤醒动作是在jvm里做的,在gc完成后会调用如下方法VM_GC_Operation::doit_epilogue(),在方法末尾会调用lock的notify操作,至于pending队列是什么时候讲引用放进去,其实是在gc的引用处理逻辑中放进去的

void VM_GC_Operation::doit_epilogue() {
  assert(Thread::current()->is_Java_thread(), "just checking");
  // Release the Heap_lock first.
  SharedHeap* sh = SharedHeap::heap();
  if (sh != NULL) sh->_thread_holds_heap_lock_for_gc = false;
  Heap_lock->unlock();
  release_and_notify_pending_list_lock();
}

void VM_GC_Operation::release_and_notify_pending_list_lock() {
instanceRefKlass::release_and_notify_pending_list_lock(&_pending_list_basic_lock);
}

 

为什么要使用堆外内存以及为什么不能大面积使用堆外内存看原文

分享到:
评论

相关推荐

    HBase堆外内存测试

    ### HBase堆外内存测试详解 #### 一、HBase BlockCache概述 HBase的BlockCache是一种用于提高读取性能的重要机制,它主要用于缓存HFile的Block数据,以减少磁盘I/O操作,从而加快读取速度。BlockCache分为两种类型...

    堆外内存部分代码

    5. **性能优化**:堆外内存的使用可以提高大数据处理或高并发场景下的性能,但过度依赖堆外内存可能导致内存碎片,需要权衡利弊并进行适当优化。 6. **元空间(Metaspace)**:自Java 8开始,元空间取代了之前的...

    Java堆外内存泄露场景总结.pdf

    Java堆外内存泄露场景总结,包含几个常用的可能,如:JNI,NIO,AWT/Swing,Inflater&Deflater;

    深入解读 Java 堆外内存(直接内存)1

    【深入解读 Java 堆外内存(直接内存)】 Java 堆外内存,又称直接内存(Direct Memory),是 Java 程序中除JVM堆内存之外的一种内存区域。它并不遵循JVM规范中定义的标准内存模型,而是直接与操作系统交互,用于...

    Java堆外内存的使用Java开发Java经验技巧共5页

    Java开发中的堆外内存使用是优化程序性能的重要策略之一,尤其在处理大数据、高并发或者内存敏感的应用场景中。堆外内存,也被称为直接内存(Direct Memory),是指不在JVM的堆内存中分配的内存,而是直接在操作系统...

    Java开发者必须了解的堆外内存技术.docx

    Java 开发者在深入理解内存管理时,不能忽视堆外内存这一重要概念。堆外内存,也称为直接内存(DirectMemory),是指在JVM堆内存之外分配的内存区域。它并非JVM规范定义的标准内存区域,但因其在IO操作中的性能优势...

    分析堆外内存.pdf

    在Linux下,使用gperftools分析对外内存泄漏。介绍了基本的安装和使用。

    Java堆外内存使用分析详细

    这个视频指导我们java开发遇到堆内存使用正常、gc正常,但实际使用的物理内存缺非常高,特别是容器化部署很容易因内存使用超limit限制导致pod重启,怀疑堆外内存泄露?如何排查堆外内存的使用情况,这个视频详细讲解...

    生产环境里的堆外内存HBase读路径——阿里巴巴的故事

    Yu Li explains how Alibaba met the challenge of tens of millions requests per second to its Alibaba-Search HBase cluster on 2016 Singles' Day. With read-path off-heaping, Alibaba improved the ...

    slice:Java库,可有效处理堆内存和堆外内存

    堆外内存,也称为直接内存或本地内存,是指不通过Java虚拟机堆分配的内存,它绕过了Java垃圾收集机制,能提供更快的访问速度,但同时也需要开发者手动管理内存释放,避免内存泄漏。 **Slice库的关键特性** 1. **堆...

    浅谈Java堆外内存之突破JVM枷锁

    浅谈Java堆外内存之突破JVM枷锁 本文主要介绍了Java堆外内存的概念,包括JVM内存分配、JVM垃圾回收、堆外内存的垃圾回收等相关内容。Java开发者都知道,Java中不需要手动申请和释放内存,JVM会自动进行垃圾回收;而...

    Java堆外内存的使用

     堆外内存其实并无特别之处。线程栈,应用程序代码,NIO缓存用的都是堆外内存。事实上在C或者C++中,你只能使用未托管内存,因为它们默认是没有托管堆(managed heap)的。在Java中使用托管内存或者“堆”内存是这...

    mapdb,mapdb提供由磁盘存储或堆外内存支持的并发映射、集合和队列。它是一种快速、易于使用的嵌入式Java数据库引擎。.zip

    MapDB 是一个强大的开源项目,它为Java开发者提供了一种高效、灵活的解决方案,用于在磁盘或堆外内存中存储并发映射、集合和队列。作为一个嵌入式数据库引擎,MapDB的设计目标是简单易用,同时保持高性能和低资源...

    gperftools-ghc-example:在Haskell程序中发现堆外内存泄漏的示例

    这是一个简单的项目,显示了如何使用来查找Haskell程序中的堆外内存泄漏。该程序测试程序以两种不同方式分配堆外内存。 首先,通过直接调用mallocBytes ,其次,通过调用本身发生的库函数间接调用mallocBytes 。 ...

    RxCache:适用于Java和Android的本地React式缓存。 现在,它支持堆内存,堆外内存和磁盘缓存

    目前支持内存、堆外内存、磁盘缓存。 功能特点: 支持二级缓存:Memory、Persistence 各个缓存可以拥有有效时间,超过时间缓存会过期 Memory 默认支持 FIFO、LRU、LFU 算法的实现 Memory 额外支持 Guava Cache、...

    largecollections-retired:使用堆外内存扩展到数百万个元素的 HashMap 实现

    Java Collections 实现,使用堆外内存扩展到数百万个元素,而不会遇到 GC 错误。 它利用 Google 的 LevelDB 项目来实现这一点。 目前这个 API 支持三种类型的 Collections java.util.Map java.util.List...

    UnsafeAdapter:一个工具包,用于协助使用Java Unsafe类来分配和管理本地堆外内存块

    《使用UnsafeAdapter进行Java堆外内存管理》 Java的`Unsafe`类是Java语言中一个强大的工具,它提供了对内存的直接访问和控制,包括在堆外分配内存、执行无同步的字节码操作等。然而,由于其潜在的安全风险和易用性...

    Go-fastcache-Go的快速堆外线程安全内存缓存

    快速。 性能在多核CPU上扩展。线程安全的。 并发goroutine可以读写单个缓存实例。fastcache设计用于存储大量项目而无需GC开销。 Fastcache在创建期间达到设置的最大大小时会自动驱逐旧条目。

    Apache Spark 内存管理详解

    堆外内存是在JVM堆外的系统内存中开辟的空间,可以有效减少垃圾回收(GC)带来的性能开销。堆外内存主要用于以下场景: - **缓存**:可以将RDD的数据缓存在堆外内存中。 - **序列化**:对于需要序列化的数据,可以在...

    Java直接(堆外)内存使用详解

    本篇主要讲解如何使用直接内存(堆外内存),并按照下面的步骤进行说明:  相关背景–>读写操作–>关键属性–>读写实践–>扩展–>参考说明  希望对想使用直接内存的朋友,提供点快捷的参考。  数据类型  ...

Global site tag (gtag.js) - Google Analytics