“堆上”和“堆外”之间的区别

问题描述 投票:122回答:6

Ehcache talks about on-heap和off-heap内存。有什么不同?使用什么JVM args来配置它们?

java memory heap ehcache
6个回答
150
投票

堆上存储引用将存在于Java堆中的对象(并且还受GC影响)。另一方面,堆外存储是指由EHCache管理但存储在堆外(并且不受GC影响)的(序列化)对象。由于堆外存储继续在内存中进行管理,它比堆上存储稍慢,但仍然比磁盘存储更快。

在堆内存储的管理和使用中涉及的内部细节在问题中发布的链接中并不十分明显,因此最好查看用于管理磁盘存储的Terracotta BigMemory的详细信息。 。 BigMemory(堆外存储)用于避免GC在几兆字节或千兆字节大的堆上的开销。 BigMemory通过direct ByteBuffers使用JVM进程的内存地址空间,与其他本机Java对象不同,它不受GC的约束。


83
投票

来自http://code.google.com/p/fast-serialization/wiki/QuickStartHeapOff

什么是堆卸载?

通常,您分配的所有非临时对象都由java的垃圾收集器管理。尽管VM在进行垃圾收集方面做得不错,但在某个时刻VM必须执行所谓的“Full GC”。完整的GC涉及扫描完整分配的堆,这意味着GC暂停/减速与应用程序堆大小成比例。所以不要相信任何人告诉你'记忆力很便宜'。在java内存中,消耗会损害性能。此外,使用堆大小> 1 Gb时,您可能会得到显着的暂停。如果您有任何接近实时的事情,在群集或网格中,Java进程可能无响应并从群集中删除,这可能是令人讨厌的。

然而,今天的服务器应用程序(通常建立在庞大的框架之上;-))很容易需要远远超过4Gb。

这些内存要求的一个解决方案是将对象的一部分“卸载”到非java堆(直接从OS分配)。幸运的是,java.nio提供了直接分配/读取和写入“非托管”内存块(甚至是内存映射文件)的类。

因此,可以分配大量的“非托管”内存,并使用它来保存那里的对象。为了将任意对象保存到非托管内存中,最可行的解决方案是使用序列化。这意味着应用程序将对象序列化到offheap内存中,稍后可以使用反序列化来读取对象。

由Java VM管理的堆大小可以保持很小,因此GC停顿在毫秒,每个人都很高兴,完成工作。

很明显,这种关闭堆缓冲区的性能主要取决于序列化实现的性能。好消息:由于某些原因,FST序列化非常快:-)。

示例使用场景:

  • 服务器应用程序中的会话缓存。使用内存映射文件存储千兆字节(非活动)用户会话。一旦用户登录到您的应用程序,您就可以快速访问与用户相关的数据,而无需处理数据库。
  • 缓存计算结果(查询,html页面,..)(仅适用于计算比反序列化结果对象ofc更慢的情况)。
  • 使用内存映射文件非常简单快速

编辑:对于某些情况,可以选择更复杂的垃圾收集算法,如ConcurrentMarkAndSweep或G1,以支持更大的堆(但这也有超过16GB堆的限制)。还有一个商用JVM,具有改进的“无暂停”GC(Azul)。


34
投票

堆是内存中动态分配的对象所在的位置。如果你使用new那么它就在堆上。这与堆栈空间相反,堆栈空间是函数堆栈所在的位置。如果您有一个局部变量,那么该引用就在堆栈上。 Java的堆可以进行垃圾收集,对象可以直接使用。

EHCache的堆外存储将您的常规对象从堆中取出,对其进行序列化,并将其作为字节存储在EHCache管理的一块内存中。这就像将它存储到磁盘,但它仍然在RAM中。对象不能直接在此状态下使用,必须首先对它们进行反序列化。也不受垃圾收集。


14
投票

In short picture

Java On/Off Heap storage in short

pic credits


Detailed picture

pic credits


1
投票

JVM对堆外内存一无所知。 Ehcache实现了磁盘缓存以及内存缓存。


1
投票

不是100%;然而,这听起来像堆是一个对象或一组分配的空间(在RAM上),它构建在代码的功能中,或者是Java本身,或者更可能是来自ehcache本身的功能,而堆外的Ram则有自己的系统。好;但是,听起来这个速度要慢一些,因为它不是有组织的,这意味着它可能不会使用堆(意味着一组长的ram空间),而是使用不同的地址空间,这可能会使效率略低。

当然,下一层更低的是硬盘空间本身。

我不使用ehcache,所以你可能不想相信我,但那是我从他们的文档中收集的内容。

© www.soinside.com 2019 - 2024. All rights reserved.