在32位到64位的转变中,人们最大的获益是内存容量。在一个32位的系统中,内存地址的宽度就是32位,这就意味着,我们最大能获取的内存空间是2^32(也就是4G)字节。这个容量明显不够用!在一个64位的机器中,理论上,我们能获取到的内存容量是2^64字节,这是一个十分庞大的数字。可惜的是,这只是一个理论值,而现实中,因为有一堆有关硬件和软件的因素限制,我们能得到的内存要少得多。举个例了来说,最好的 linux 系统最多支持到16TB的内存,而且截止到现在 java11 也在正在研制最新一代的垃圾收集器 ZGC ,号称可以支持到 TB 几倍的且能保证 STW 时间不会太长,可能许多人会说“16TB好大呀”,但是和2^64比起来,它真的挺小的。好了,接下来,我们就谈谈compressed oops能帮我们做什么。

什么是 OOP ?

在堆中,32位的对象引用(指针)占4个字节,而64位的对象引用占8个字节。64位JVM在支持更大堆的同时,由于对象引用变大却带来了性能问题:

1. 增加了GC开销:64位对象引用需要占用更多的堆空间,留给其他数据的空间将会减少,从而加快了GC的发生,更频繁的进行GC。

2. 降低CPU缓存命中率:64位对象引用增大了,CPU能缓存的oop将会更少,从而降低了CPU缓存的效率。

为了能够保持32位的性能,oop必须保留32位。那么,如何用32位oop来引用更大的堆内存呢?答案是——压缩指针(CompressedOops)。

OOP = “ordinary object pointer” 普通对象指针。 启用CompressOops后,会压缩的对象:

1. 每个Class的属性指针(静态成员变量)

2. 每个对象的属性指针

3. 普通对象数组的每个元素指针

当然,压缩也不是万能的,针对一些特殊类型的指针,JVM是不会优化的。 比如指向 PermGen的Class 对象指针,本地变量,堆栈元素,入参,返回值,NULL指针不会被压缩

1)CompressedOops原理:

JVM的实现方式是,不再保存所有引用,而是每隔8个字节保存一个引用。例如,原来保存每个引用0、1、2...,现在只保存0、8、16...。因此,指针压缩后,并不是所有引用都保存在堆中,而是以8个字节为间隔保存引用。

CompressedOops,可以让跑在64位平台下的JVM,不需要因为更宽的寻址,而付出Heap容量损失的代价。 不过它的实现方式是在机器码中植入压缩与解压指令,可能会给JVM增加额外的开销。

2)零基压缩优化(Zero Based Compressd Oops)

零基压缩是针对 压、解压 动作的进一步优化。 它通过改变正常指针的随机地址分配特性,强制堆地址从零开始分配(需要OS支持),进一步提高了压解压效率。要启用零基压缩,你分配给JVM的内存大小必须控制在4G以上,32G以下。

3)总结:

如果GC堆大小在 4G以下,直接砍掉高32位,避免了编码解码过程;

如果GC堆大小在 4G以上32G以下,则启用 UseCompressedOop;

如果GC堆大小 大于32G,压指失效,使用原来的64位(所以说服务器内存太大不好......)。

灵魂提问

从以上结果中我们知道 32GB 以下是启用了 UseCompressedOop,但是当我们线上真正启动服务的时候直接设置 -Xmx=32GB 的时候很可能导致 CompressedOop 失效,那我们怎么确定当前环境下最大内存设置多大才且最大限度的使用内存才能启动 CompressedOop 呢?

32G是个近似值,这个临界值跟JVM和平台有关。如果不想精确设置的话,31G是个绝对安全的数值,31G肯定默认开启compressed oops。我们可以通过增加JVM参数 -XX:+PrintFlagsFinal,验证UseCompressedOops的值,从而得知,到底是不是真的开启了压缩指针,还是压缩指针失效!

那我们就手动来验证这个临界值:

32G,即32*1024=32768M,刚好在范围[32760, 32770]中。而 32768m 验证后得到并没有开启压缩指针,所以可以从 32760 ~ 32768 之间验证选择一个最大的且开启压缩指针的内存大小。

简单测试验证

我们来做了一个简单测试,验证一下这个问题:分配设置内存大小分别为:-Xmx32760m 和 -Xmx32770m,-Xmn 都是 100M(S0:S1:Eden默认1:1:8)。总计分配一个包含8个对象类型和8个原子类型以及String,总计17个类型属性的对象 1kw 次。看它们分别触发了多少 YGC,结论如下表所示:

实验次数    开启压缩指针YGC次数    关闭压缩指针YGC次数

由执行结果可知,Young区完全一样的情况下,开启压缩指针相比关闭压缩指针,能节省20%多的内存。由此可知,32G还真是一个奇妙的魔法数值!另外需要说明的是YGC次数有小数,是表示Eden区占用比例,比如 17.52 次 YGC 表示发生了 17次 YGC 并且 Eden 还占了52%

java 内存压缩_JVM之指针压缩内存如何设置相关推荐

  1. 【C 语言】结构体 ( 结构体中嵌套一级指针 | 分配内存时先 为结构体分配内存 然后再为指针分配内存 | 释放内存时先释放 指针成员内存 然后再释放结构头内存 )

    文章目录 一.结构体中嵌套一级指针 1.声明 结构体类型 2.为 结构体 变量分配内存 ( 分配内存时先 为结构体分配内存 然后再为指针分配内存 ) 3.释放结构体内存 ( 释放内存时先释放 指针成员 ...

  2. linux c 指针和内存分配内存,Linux C语言指针与内存学习笔记

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 环境准备 Ubuntu 操作系统.VIM 编辑器.GCC 编译器.GDB调试器. 初始指针 通过两个数的交换引入指针指针 ...

  3. java 指针 地址压缩_JVM优化之压缩普通对象指针(CompressedOops)

    通常64位JVM消耗的内存会比32位的大1.5倍,这是因为对象指针在64位架构下,长度会翻倍(更宽的寻址). 对于那些将要从32位平台移植到64位的应用来说,平白无辜多了1/2的内存占用,这是开发者不 ...

  4. java堆外内存溢出_JVM 案例 - 堆外内存导致的溢出错误

    案例 一个网站为了实现客户端实时从服务端接收数据,使用了 CometD 1.1.1 作为服务端推送框架,服务器是 Jetty7.1.4,CPU i5,内存 4G,操作系统 32位Windows. 服务 ...

  5. JAVA对象头的指针压缩

    JAVA对象头的指针压缩 文章目录 JAVA对象头的指针压缩 对象在JVM中的内存布局 对象的访问定位 压缩实验 实验步骤 压缩策略组合 压缩内容 压缩后的影响 指针压缩的实现 JVM内存关键大小 对 ...

  6. 【C 语言】结构体 ( 结构体中嵌套二级指针 | 为 结构体内的二级指针成员 分配内存 | 释放 结构体内的二级指针成员 内存 )

    文章目录 一.结构体中嵌套二级指针 1.结构体中嵌套二级指针 类型声明 2.为 结构体内的二级指针成员 分配内存 3.释放 结构体内的二级指针成员 内存 二.完整代码示例 一.结构体中嵌套二级指针 1 ...

  7. 【Android 内存优化】Android 工程中使用 libjpeg-turbo 压缩图片 ( 初始化压缩对象 | 打开文件 | 设置压缩参数 | 写入压缩图像数据 | 完成压缩 | 释放资源 )

    文章目录 一.使用 libjpeg-turbo 压缩图片流程 二.初始化 JPEG 压缩对象 三.打开文件 四.设置压缩参数 五.开始压缩 六.循环写入压缩数据 七.完成图片压缩及收尾 八.libjp ...

  8. JVM - 剖析Java对象头Object Header之指针压缩

    文章目录 Pre 指针压缩 论证压缩效果 UseCompressedOops & UseCompressedClassPointers [指针压缩]开启 VS 关闭 指针压缩的目的 为什么堆内 ...

  9. java 栈内存结构_JVM内存结构概念解析

    一. Java 内存结构 Java代码运行在虚拟机上,虚拟机在运行过程将程序(也就是进程)所占有内存分为几个不同的数据区域.不同的区域有不同的职责. Java运行时内存结构图如下: Java运行时内存 ...

最新文章

  1. Android TextView文本处理库推荐
  2. c++ getline 读不到东西_C++ getline()函数问题
  3. php解析乱码字符串,PHP substr 截取字符串出现乱码问题解决方法[utf8与gb2312]
  4. DropDownList 控件不能触发SelectedIndexChanged 事件的另一个原因
  5. 了解和扩展Java ClassLoader
  6. 报错型sql注入原理分析
  7. String转LocalDateTime
  8. ETL工具kettle之Java脚本+Elasticsearch bulk insert
  9. Google地图下载器制作
  10. No tracked branch configured for branch master or the branch doesn‘t exist
  11. iphone拍照标注转发微博应用--Gurgle 发布
  12. 香港流行乐坛三十年(很好的回忆)
  13. [OpenAirInterface实战-5] :OAI支持的5G gNB功能集
  14. CF 1715 D. 2+ doors 位运算 1900
  15. 特种浓缩分离:生物农药超滤分离提纯过滤技术
  16. opencv基础笔记
  17. [ARCGIS]带黑边的IMG格式影像如何消除黑边?
  18. JavaScript window.alert
  19. 【Python自查手册】之项目实操
  20. 要求: 编写一个程序,提示用户输入: 姓名 ,身份证号(需要一次输完,中间用逗号分隔)随后打印用户的星座。 提示:输入功能用C实现会很简单,其他语言的话,就不用输入姓名和逗号了,直接输入身份证号就

热门文章

  1. html 标签对应的英文
  2. 联芯 1860平台 icn6211 mipi to RGB 转换芯片 调试 和 st7789 LCD调试spi 9bit 模式
  3. 全球及中国冬装外套行业市场需求及投资前景调研报告2022-2027年
  4. android 特效相机实现,基于Android系统的相机特效软件的设计与实现
  5. OpenCV C++录制视频录制与播放
  6. 花儿绽放斩获金梧奖金奖,智能营销赋能品牌增长
  7. 单片机学习入门 我们应该这样学习单片机
  8. jsp+Servlet+javaBean编写计算体重指数测量(BMI)的简单程序
  9. Adobe25年软件精华CS3中文版发布.
  10. SpringBoot报错Field userService in XXTestController required a bean of type 'XX' that could not be...