技术团队通过 GCeasy 工具分析完几千次用户上传的GC日志后, 发现一个现象: 仍然有很多Java程序传入了JVM启动参数 -XX:+UseCompressedOops。
实际上,如果JVM的版本在 Java SE 6 update 23 及以上, 则不需要再设置 -XX:+UseCompressedOops 参数, 因为默认会开启。
“OOP” 表示普通对象指针(Ordinary Object Pointer), 这种指针是对某个对象的托管指针(managed pointer)。 OOP占用的空间长度通常与宿主机的原生指针(native machine pointer)一样; 也就是说, 在64位 *** 作系统上OOP就是64位, 在32位 *** 作系统上OOP就占32位。
由于 *** 作系统的限制,32位版本的JVM, 内存地址空间最大只能到 4GB(2 ^ 32字节)。
如果要管理更大的内存,需要使用64位JVM。
而如果JVM使用64位OOP,则最多可以管理 18.5 Exabytes(2 ^ 64字节)。
这是一个非常大的空间。 当今世界上还没有哪台服务器有这么大的物理内存。
那么问题来了: 64位JVM上, 使用32位的压缩指针如何管理32GB内存呢?
我们可以注意到 4x8=32; 想一下, 如果内存地址使用8字节对齐(8x8=64bit), 再进行映射和换算, 是不是就可以放大8倍了?
当然, 这样处理的话, 要更精细的 *** 作单个字节就不容易了。
想要了解JVM的内存布局和对齐机制, 可以参考: 解析一个Java对象占用多少内存空间
存储指针的内存空间放大1倍,可以定位更大的内存区域。
但这并非 “没有代价”。
从32位JVM切换到64位JVM,你会发现可用内存的消耗会变成原来的1.5倍左右, 这是因为存储地址指针的空间消耗变大了。
为了解决这个问题,JVM开发人员发明了 Compressed Oops 功能。 关于压缩指针(compressed OOPs)的详细信息请参考: HotSpot JVM Performance Enhancements
。
要启用这个功能,可以传入JVM启动参数 -XX:+UseCompressedOops。
但从 Java SE 6U23 开始,JVM会默认开启压缩指针。
因此, 我们不需要再手动传递这个参数。
- 原文链接: Avoid passing -XX:+UseCompressedOops
- GitHub版本: 不需要再手工指定JVM启动参数 -XX:+UseCompressedOops
- Gitee版本: 不需要再手工指定JVM启动参数 -XX:+UseCompressedOops
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)