写点什么

堆内内存还是堆外内存?

  • 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:229583
用户头像

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

关注

评论

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

阿里自爆性能优化100+小技巧,Github已获赞68.7K

Java 性能优化 性能调优

GitHub爆赞!阿里P9纯手打十亿级高并发系统手册,真的太香了!

Java 系统设计 高并发 亿级并发

Java开发实践:合理使用线程池及线程变量

阿里技术

Java 线程池

GitHub笔记疯抢竟崩溃!Redis完整开发实战居然包含大厂同款项目

Java你猿哥

Java redis ssm java面试 Redis 核心技术与实战

记录一次解决Maven依赖冲突的过程

Java maven

23年最新Java岗常见面试题及答案(1000道),90% 的公司都会问到

Java你猿哥

Java MySQL zookeeper JVM java面试

阿里首席架构师讲解“双十一”亿级流量高并发的系统架构搭建方法

Java 系统设计 高并发 亿级流量

GitHub万赞,不愧是腾讯大牛总结的操作系统笔记,面面俱到太全了

Java你猿哥

Java 面试 多线程 ssm 线程与进程

玩转Netty,从“Hello World”开始!

Java你猿哥

Java Netty ssm

研发效能管理中的经典度量——DORA 指标

LigaAI

DevOps 敏捷开发 研发管理 研发效能管理 企业号 5 月 PK 榜

阿里云数据库ClickHouse产品和技术解读

NineData

MySQL 数据库 运维 Clickhouse 2023云数据库技术沙龙

极狐GitLab as Code,全面升级你的 GitOps 体验

极狐GitLab

git DevOps 云原生 版本控制 gitops

MobLink 创建应用

MobTech袤博科技

volatile 关键字与计算机底层的一些杂谈

Java你猿哥

Java volatile JVM ssm java知识点

使用doop识别最近commons text漏洞的污点信息流

vivo互联网技术

SAST commons text命令执行漏洞 doop

SecureCRT中文乱码怎么办?解决 SecureCRT中文乱码方法

互联网搬砖工作者

阿里Java面试脑图 被曝光!GitHub上已获赞79.6K

Java java面试 Java八股文 Java面试题 Java面试八股文

使用 Python 和 mitmproxy 实现基于队列的路径管理

IT蜗壳-Tango

Java字节码 - ByteBuddy原理与使用(下)

骑牛上青山

Java bytebuddy 字节码

面试官:断网了,还能 ping 通 127.0.0.1 吗?

Java你猿哥

Java 架构 ssm ping

百万年薪大佬甩出的SpringBoot趣味实战手册,GitHub标星81.6K

Java你猿哥

redis spring Spring Boot Spring MVC 消息队列对比

开箱即用!AI模型库全新发布,一站式在线开发部署!

飞桨PaddlePaddle

模型 飞桨

AIGC产业研究报告2023——语言生成篇

易观分析

智能 制造

SVN管理工具Cornerstone入门教程

互联网搬砖工作者

首个支持RWA交易的订单簿DEX-PoseiSwap,即将开启IEO

鳄鱼视界

Python从零到壹丨详解图像锐化Roberts、Prewitt算子实现边缘检测

华为云开发者联盟

人工智能 华为云 图像 华为云开发者联盟 企业号 5 月 PK 榜

本周精彩!关于 Linux 内核宕机和超融合 Kata 虚拟化容器技术介绍 | 第 77-78 期

OpenAnolis小助手

开源 云原生 系统运维 龙蜥大讲堂 浪潮

Makefile基础教程:从零开始学习

小万哥

程序员 面试 后端 C/C++ makefile

四大关键举措!高效管控企业税务风险

用友BIP

税务

Rhino 7 中文:建模渲染一站式完成~

真大的脸盆

Mac 3D Mac 软件 三维建模 建模软件

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