Answers:
堆上存储是指将在Java堆中存在的对象(也受GC约束)。另一方面,堆外存储引用(序列化的)对象,这些对象由EHCache管理,但是存储在堆外部(并且不受GC限制)。随着堆外存储继续在内存中进行管理,它比堆上存储稍慢,但仍比磁盘存储快。
问题中发布的链接中并没有非常清楚地涉及到管理和使用堆外存储的内部细节,因此明智的方法是查看用于管理磁盘外的Terracotta BigMemory的细节。商店。BigMemory(堆外存储)用于避免GC在数兆字节或千兆字节的堆上的开销。BigMemory通过直接的ByteBuffer使用JVM进程的内存地址空间,与其他本机Java对象不同,这些直接ByteBuffer不受GC影响。
来自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提供了一些类来直接分配/读取和写入“非托管”内存块(甚至是内存映射文件)。
因此,人们可以分配大量的“非托管”内存,并用它来保存对象。为了将任意对象保存到非托管内存中,最可行的解决方案是使用序列化。这意味着应用程序将对象序列化到堆内存中,随后可以使用反序列化读取对象。
由Java VM管理的堆大小可以保持较小,因此GC暂停在毫秒级,每个人都很高兴,工作已经完成。
显然,这种堆外缓冲区的性能主要取决于序列化实现的性能。好消息:出于某种原因,FST序列化非常快:-)。
示例使用场景:
编辑:在某些情况下,可能会选择更复杂的垃圾收集算法,例如ConcurrentMarkAndSweep或G1以支持更大的堆(但这在16GB堆之外也有其限制)。还有一个具有改进的“无中断” GC(Azul)的商业JVM。
堆是内存中动态分配的对象所在的位置。如果使用过,new
那么它就在堆上。这与函数空间所在的堆栈空间相反。如果您有局部变量,则该引用位于堆栈上。Java的堆受垃圾回收的限制,并且这些对象可以直接使用。
EHCache的堆外存储将常规对象移出堆,对其进行序列化,并将其作为字节存储在EHCache管理的内存块中。这就像将其存储到磁盘,但仍在RAM中。对象在这种状态下不能直接使用,必须先对其进行反序列化。也不受垃圾收集的限制。