写点什么

堆内内存还是堆外内存?

  • 2014-12-28
  • 本文字数:1239 字

    阅读完需:约 4 分钟

一般情况下,Java 中分配的非空对象都是由 Java 虚拟机的垃圾收集器管理的,也称为堆内内存(on-heap memory)。虚拟机会定期对垃圾内存进行回收,在某些特定的时间点,它会进行一次彻底的回收(full gc)。彻底回收时,垃圾收集器会对所有分配的堆内内存进行完整的扫描,这意味着一个重要的事实——这样一次垃圾收集对 Java 应用造成的影响,跟堆的大小是成正比的。过大的堆会影响 Java 应用的性能。

对于这个问题,一种解决方案就是使用堆外内存(off-heap memory)。堆外内存意味着把内存对象分配在 Java 虚拟机的堆以外的内存,这些内存直接受操作系统管理(而不是虚拟机)。这样做的结果就是能保持一个较小的堆,以减少垃圾收集对应用的影响。

但是 Java 本身也在不断对堆内内存的实现方式做改进。两者各有什么优缺点? Vanilla Java 博客作者 Peter Lawrey 撰写了一篇文章,在文中他对三种方式:用 new 来分配对象、对象池(object pool)和堆外内存,进行了详细的分析。

用 new 来分配对象内存是最基本的一种方式,Lawery 提到:

在 Java 5.0 之前,分配对象的代价很大,以至于大家都使用内存池。但是从 5.0 开始,对象分配和垃圾回收变得快多了,研发人员发现了性能的提升,纷纷简化他们的代码,不再使用内存池,而直接用 new 来分配对象。从 5.0 开始,只有一些分配代价较大的对象,比如线程、套接字和数据库链接,用内存池才会有明显的性能提升。

对于内存池,Lawery 认为它主要用于两类对象。第一类是生命周期较短,且结构简单的对象,在内存池中重复利用这些对象能增加 CPU 缓存的命中率,从而提高性能。第二种情况是加载含有大量重复对象的大片数据,此时使用内存池能减少垃圾回收的时间。对此,Lawery 还以 StringInterner 为例进行了说明。

最后 Lawery 分析了堆外内存,它和内存池一样,也能缩短垃圾回收时间,但是它适用的对象和内存池完全相反。内存池往往适用于生命期较短的可变对象,而生命期中等或较长的对象,正是堆外内存要解决的。堆外内存有以下特点:

  • 对于大内存有良好的伸缩性
  • 对垃圾回收停顿的改善可以明显感觉到
  • 在进程间可以共享,减少虚拟机间的复制

Lawery 还提到对外内存最重要的还不是它能改进性能,而是它的确定性。

当然堆外内存也有它自己的问题,最大的问题就是你的数据结构变得不那么直观,如果数据结构比较复杂,就要对它进行串行化(serialization),而串行化本身也会影响性能。另一个问题是由于你可以使用更大的内存,你可能开始担心虚拟内存(即硬盘)的速度对你的影响了。

Lawery 还介绍了 OpenHFT 公司提供三个开源库: Chronicle Queue Chronicle Map Thread Affinity ,这些库可以帮助开发人员使用堆外内存来保存数据。采用堆外内存有很多好处,同时也带来挑战,对堆外内存感兴趣的读者可以阅读 Lawery 的原文来了解更多信息。


感谢郭蕾对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2014-12-28 07:229618
用户头像

发布了 77 篇内容, 共 39.4 次阅读, 收获喜欢 26 次。

关注

评论

发布
暂无评论
发现更多内容

前端的状态管理与时间旅行:San实践篇

百度开发者中心

大前端 san san-store 技术实践

NodeJs深入浅出之旅:内存控制(下)🐯

空城机

大前端 Node 11月日更

十月热点:EasyDL八大国产芯片实现模型部署全适配,度目智能门禁机CM-A1重磅发布!

百度大脑

人工智能 百度

点进来,与白洞一起体验一场沉浸式智慧轨道之旅

脑极体

“元宇宙”到底是啥?为啥火了?鼓励探索警惕忽悠

CECBC

译文 | 科普:Pulsar 和 Kafka 架构对比

Apache Pulsar

kafka 架构 分布式 中间件 Apache Pulsar

Go 语言,测试功能详解 - 下

微客鸟窝

Go 语言 11月日更

如何穿透ToB客户生命周期的全链增长?

ToB行业头条

开源数据库风起云涌,openGauss 恰逢其时

#数据库

VR和AR只是入门,真正的元宇宙远不止于此

CECBC

Ta们用数字种植绿色山河:牛津博士与储能之变

脑极体

自定义View:多点触摸与实现任意拖动图片控

Changing Lin

11月日更

从 Linux源码 看 Socket(TCP)的accept

赖猫

c++ Linux 后端 服务器 epoll

【云小课】如何初步定位GaussDB(for openGauss)慢SQL

华为云数据库小助手

GaussDB GaussDB(for openGauss) 华为云数据库

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

不脱发的程序猿

Python PyQt GUI 计时器 多线程类和事件处理

博文推荐 | Apache Pulsar 对现代数据堆栈至关重要的四个原因

Apache Pulsar

kafka 架构 Apache Pulsar 数据堆栈 DataStax

一个基于DPoS共识算法的区块链案例解析

Regan Yue

区块链 11月日更 细讲区块链

Nginx中间件渗透总结

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 漏洞挖掘

北鲲云超算携手西安电子科技大学开展高性能计算培训

北鲲云

【Quarkus技术系列】「云原生架构体系」配置参考指南相关的功能机制配置介绍分析

码界西柚

入门 配置信息 Quarkus 11月日更

什么是低代码平台?

石云升

低代码平台 11月日更

经验分享|参与内部开源的心路历程

云智慧AIOps社区

大前端 数据可视化 知识分享 开源治理 flyfish

盲盒app开发

一文讲透自适应熔断的原理和实现

万俊峰Kevin

微服务 熔断 Go 语言 熔断器 限流熔断

堪称“高并发”教程天花板的Alibaba《基础+实战+源码+面试+架构》

收到请回复

Java 程序员 后端 java面试

双十一还是孤身一人?超强AI神器送你一个"对象"

百度大脑

人工智能 百度

你找的网络安全系列书籍,都在这了!

喀拉峻

网络安全 安全 信息安全

浅谈 RDMA 与无损网络

青云技术社区

云计算 云原生 存储

openGauss支持国密SM3和SM4算法

#数据库

Web 用户体验设计提升实践

Shopee技术团队

大前端 web开发 用户体验 交互设计 可访问性

11.25直播预告|开源与SaaS水火不容?「观测云-可观测之路」第2期技术大咖为您解惑!

观测云

堆内内存还是堆外内存?_语言 & 开发_曹知渊_InfoQ精选文章