JVM常用概念之对象对齐

问题

对象对齐有什么规范吗?对象对齐是8个字节吗?

基础知识

许多硬件实现要求对数据的访问是对齐的,即确保所有 N 字节宽度的访问都在 N 的整数倍的地址上完成。即使对于普通的数据访问没有特别要求,特殊操作(特别是原子操作)通常也有对齐约束。

例如,x86 通常可以接受未对齐的读取和写入,同时跨越两个缓存行的未对齐 CAS 仍然有效,但它会降低吞吐量性能。其他架构会直接拒绝执行此类原子操作,从而产生SIGBUS或其他硬件异常。x86 也不保证跨越多个缓存行的值的访问原子性,当访问未对齐时,这种情况是可能发生的。另一方面,Java 规范要求大多数类型都具有访问原子性,并且绝对要求所有volatile访问都具有访问原子性。

因此,如果 Java 对象中有long字段,并且它在内存中占用 8 个字节,那么出于性能原因,我们必须确保它按 8 个字节对齐。如果该字段是volatile ,那么出于正确性原因,也必须这样做。简单来说,要使这一点成立,需要发生两件事:对象内部的字段偏移量应按 8 个字节对齐,并且对象本身应按 8 个字节对齐。如果我们查看java.lang.Long实例,就会看到这一点:

$ java -jar jol-cli.jar internals java.lang.Long
# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]java.lang.Long object internals:OFFSET  SIZE   TYPE DESCRIPTION              VALUE0     4        (object header)          01 00 00 004     4        (object header)          00 00 00 008     4        (object header)          ce 21 00 f812     4        (alignment/padding gap)16     8   long Long.value               0
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

这里, value字段本身的偏移量为 16(它是 8 的倍数),并且对象按 8 对齐。

即使没有需要特殊处理的字段,仍然有对象头需要原子访问。从技术上讲,可以将大多数 Java 对象按 4 个字节对齐,而不是按 8 个字节对齐,但实现这一点所需的运行时工作量非常巨大。

因此,在 Hotspot 中,最小对象对齐是 8 个字节。但是它可以更大吗?当然可以,VM 选项可以实现这一点: -XX:ObjectAlignmentInBytes 。它会带来两个后果,一个是负面的,一个是正面的。

实例大小变大

一旦对齐变大,就意味着每个对象浪费的平均空间也会增加。例如,对象对齐增加到 16 和 128 字节:

$ java -XX:ObjectAlignmentInBytes=16 -jar jol-cli.jar internals java.lang.Longjava.lang.Long object internals:OFFSET  SIZE   TYPE DESCRIPTION                               VALUE0     4        (object header)                           01 00 00 004     4        (object header)                           00 00 00 008     4        (object header)                           c8 10 01 0012     4        (alignment/padding gap)16     8   long Long.value                                024     8        (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 4 bytes internal + 8 bytes external = 12 bytes total
$ java -XX:ObjectAlignmentInBytes=128 -jar jol-cli.jar internals java.lang.Longjava.lang.Long object internals:OFFSET  SIZE   TYPE DESCRIPTION                               VALUE0     4        (object header)                           01 00 00 004     4        (object header)                           00 00 00 008     4        (object header)                           a8 24 01 0012     4        (alignment/padding gap)16     8   long Long.value                                024   104        (loss due to the next object alignment)
Instance size: 128 bytes
Space losses: 4 bytes internal + 104 bytes external = 108 bytes total

每个实例 128 个字节,但只有 8 个字节的有用数据,这里又会有明显的内存空间的浪费。

压缩引用阈值发生偏移

通过将引用移几位来在大于 4 GB 的堆上启用压缩引用。移位的长度取决于引用中有多少低位为零。也就是说,对象是如何对齐的!默认情况下,使用 8 字节对齐,3 个低位为零,我们移位 3 位,得到 2 ( 32 + 3 ) 字节 = 32 G B 2^ {(32+3)}字节 = 32 GB 2(32+3)字节=32GB的压缩引用可寻址空间。使用 16 字节对齐,我们有 2 ( 32 + 4 ) 字节 = 64 G B 2^{(32+4)}字节 = 64 GB 2(32+4)字节=64GB的压缩引用堆!

实验

测试用例

对象对齐会使实例大小膨胀,从而增加堆占用率,但允许在更大的堆上使用压缩引用,从而减少堆占用率!这些因素会相互抵消吗?取决于堆的结构。我们可以使用之前使用的相同测试,尝试找出容纳给定数量对象的最小堆。

源码

import java.io.*;
import java.util.*;public class CompressedOopsAllocate {static final int MIN_HEAP = 0 * 1024;static final int MAX_HEAP = 100 * 1024;static final int HEAP_INCREMENT = 128;static Object[] arr;public static void main(String... args) throws Exception {if (args.length >= 1) {int size = Integer.parseInt(args[0]);arr = new Object[size];IntStream.range(0, size).parallel().forEach(x -> arr[x] = new byte[(x % 20) + 1]);return;}String[] opts = new String[]{"","-XX:-UseCompressedOops","-XX:ObjectAlignmentInBytes=16","-XX:ObjectAlignmentInBytes=32","-XX:ObjectAlignmentInBytes=64",};int[] lastPasses = new int[opts.length];int[] passes = new int[opts.length];Arrays.fill(lastPasses, MIN_HEAP);for (int size = 0; size < 3000; size += 30) {for (int o = 0; o < opts.length; o++) {passes[o] = 0;for (int heap = lastPasses[o]; heap < MAX_HEAP; heap += HEAP_INCREMENT) {if (tryWith(size * 1000 * 1000, heap, opts[o])) {passes[o] = heap;lastPasses[o] = heap;break;}}}System.out.println(size + ", " + Arrays.toString(passes).replaceAll("[\\[\\]]",""));}}private static boolean tryWith(int size, int heap, String... opts) throws Exception {List<String> command = new ArrayList<>();command.add("java");command.add("-XX:+UnlockExperimentalVMOptions");command.add("-XX:+UseEpsilonGC");command.add("-XX:+UseTransparentHugePages"); // faster this waycommand.add("-XX:+AlwaysPreTouch");          // even faster this waycommand.add("-Xmx" + heap + "m");Arrays.stream(opts).filter(x -> !x.isEmpty()).forEach(command::add);command.add(CompressedOopsAllocate.class.getName());command.add(Integer.toString(size));Process p = new ProcessBuilder().command(command).start();return p.waitFor() == 0;}
}

运行结果

在堆容量可达 100+ GB 的大型机器上运行此测试将产生可预测的结果。让我们从平均对象大小开始来设置叙述。请注意,这些是该特定测试中的平均对象大小,该测试分配了大量小的byte[]数组。如下图所示:

在这里插入图片描述
增加对齐确实会使平均对象大小膨胀:16 字节和 32 字节对齐已成功“稍微”增加了对象大小,而 64 字节对齐则使平均值大幅增加。请注意,对象对齐基本上说明了最小对象大小,一旦最小值增加,平均值也会增加。

压缩引用通常会在 32 GB 左右失败。但请注意,更高的对齐会延长这一时间,对齐越高,失败所需的时间就越长。例如,16 字节对齐会在压缩引用中发生 4 位移位,并在 64 GB 左右失败。32 字节对齐将发生 5 位移位,并在 128 GB 左右失败。 [ 3 ]在此特定测试中,在某些对象计数中,由于更高对齐导致的对象大小膨胀与由于压缩引用处于活动状态而导致的较低占用空间相平衡。当然,当压缩引用最终被禁用时,对齐成本就会赶上来。

在“最小堆大小”图中可以更清楚地看到它:
在这里插入图片描述
在这里,我们清楚地看到了 32 GB 和 64 GB 的失败阈值。请注意,在某些配置中,16 字节和 32 字节对齐占用的堆更少,这得益于更高效的引用编码。这种改进并不普遍:当 8 字节对齐足够或压缩引用失败时,更高的对齐会浪费内存。

结论

对象对齐是一件有趣的事情。虽然它大大增加了对象大小,但一旦压缩引用出现,它也可以降低整体占用空间。有时,稍微增加对齐是有意义的,以获得占用空间的好处。然而,在许多情况下,这会降低整体占用空间。需要仔细研究给定的应用程序和给定的数据集,以确定增加对齐是否有用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/36899.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8S学习之基础三十七:prometheus监控node资源

Prometheus v2.2.1 ​ 编写yaml文件&#xff0c;包含创建ns、configmap、deployment、service # 创建monitoring空间 vi prometheus-ns.yaml apiVersion: v1 kind: Namespace metadata:name: monitor-sa# 创建SA并绑定权限 kubectl create serviceaccount monitor -n monito…

leetcode127.单词接龙

本题的思路就是将所有可转换的序列相连&#xff0c;构成图&#xff0c;然后选择起始词作为广度优先遍历的起点&#xff0c;那么就能找到转换的最小步骤数 而这里的两个单词是否相连不是真的把他们弄成一张图&#xff0c;而是采用暴力枚举&#xff0c;逐个尝试替换字母&#xf…

Tr0ll2靶机详解

一、主机发现 arp-scan -l靶机ip&#xff1a;192.168.55.164 二、端口扫描、漏洞扫描、目录枚举、指纹识别 2.1端口扫描 nmap --min-rate 10000 -p- 192.168.55.164发现21端口的ftp服务开启 以UDP协议进行扫描 使用参数-sU进行UDP扫描 nmap -sU --min-rate 10000 -p- 19…

Pycharm接入DeepSeek,提升自动化脚本的写作效率

一.效果展示&#xff1a; 二.实施步骤&#xff1a; 1.DeepSeek官网创建API key&#xff1a; 创建成功后&#xff0c;会生成一个API key&#xff1a; 2. PyCharm工具&#xff0c;打开文件->设置->插件&#xff0c;搜索“Continue”&#xff0c;点击安装 3.安装完成后&…

如何在 Node.js 中使用 .env 文件管理环境变量 ?

Node.js 应用程序通常依赖于环境变量来管理敏感信息或配置设置。.env 文件已经成为一种流行的本地管理这些变量的方法&#xff0c;而无需在代码存储库中公开它们。本文将探讨 .env 文件为什么重要&#xff0c;以及如何在 Node.js 应用程序中有效的使用它。 为什么使用 .env 文…

《视觉SLAM十四讲》ch13 设计SLAM系统 相机轨迹实现

前言 相信大家在slam学习中&#xff0c;一定会遇到slam系统的性能评估问题。虽然有EVO这样的开源评估工具&#xff0c;我们也需要自己了解系统生成的trajectory.txt的含义&#xff0c;方便我们更好的理解相机的运行跟踪过程。 项目配置如下&#xff1a; 数据解读&#xff1a; …

软考高级信息系统管理工程师通关100题(21-40)附记忆口诀

文章目录 21.常用存储模式的技术与应用对比22.物联网架构23.云计算服务提供的资源层次24.大数据25.区块链26.人工智能27.虚拟现实VR28.IT治理的内涵29.IT 治理活动30.IT治理本质31.IT审计目标32.IT审计方法33.治理系统设计34.数据管理能力成熟度评估模型35.项目管理原则36.管理…

Redisson 分布式锁原理

加锁原理 # 如果锁不存在 if (redis.call(exists, KEYS[1]) 0) then# hash结构,锁名称为key,线程唯一标识为itemKey&#xff0c;itemValue为一个计数器。支持相同客户端线程可重入,每次加锁计数器1.redis.call(hincrby, KEYS[1], ARGV[2], 1);# 设置过期时间redis.call(pexpi…

主流加固方案深度剖析(梆梆/腾讯/阿里)

1. 加固技术演进与核心原理 1.1 移动端加固技术图谱 graph TD A[代码防护] --> A1[混淆] A --> A2[虚拟化] A --> A3[动态加载] B[数据防护] --> B1[资源加密] B --> B2[协议加密] C[运行时防护] --> C1[反调试] C --> C2[环境检测] C --> C…

大模型之蒸馏模型

蒸馏模型&#xff08;Distilled Model&#xff09;是一种通过知识蒸馏&#xff08;Knowledge Distillation&#xff09;技术训练得到的轻量级模型&#xff0c;其核心思想是将一个复杂的大模型&#xff08;称为教师模型&#xff09;的知识“迁移”到一个更小、更高效的模型&…

iPaaS集成平台中的API可视化编排能给企业带来什么作用

随着企业数字化转型的加速&#xff0c;API&#xff08;应用程序接口&#xff09;作为企业数字化资产的核心组成部分&#xff0c;其数量和复杂性不断增加。为了满足业务敏捷化交付的要求&#xff0c;API可视化编排平台应运而生。谷云科技作为这一领域的领先者&#xff0c;其API可…

演员马晓琳正式加入创星演员出道计划,开启演艺事业新篇章

3月19日&#xff0c;演员马晓琳正式加入“创星演员出道计划”&#xff0c;不仅得到参演都市爱情喜剧《和我结婚吧》角色的机会&#xff0c;还获得文旅精品网剧《醉梦灵州》的出演机会&#xff0c;自此开启全新影视之路。对表演抱有极大热情的马晓琳&#xff0c;相信未来可以凭借…

绿盟科技春招面试

《网安面试指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39…

双碳战略下的电能质量革命:解码电力系统的健康密码

安科瑞顾强 在能源结构转型的深水区&#xff0c;电能质量正成为制约产业升级的隐形门槛。国家能源局数据显示&#xff0c;我国工业企业每年因电能质量问题造成的经济损失高达3000亿元&#xff0c;而新能源项目因并网质量问题导致的发电效率损失超过15%。在这场关乎能源安全的攻…

Microsoft Edge浏览器的取证分析(基于Chromium)

概述 早在2019年&#xff0c;微软就用Chromium替换了EdgeHTML浏览器引擎&#xff0c;这是微软支持谷歌Chrome浏览器的一个开源项目。通过切换到Chromium&#xff0c;Edge与Chrome浏览器共享一个共同的架构&#xff0c;这意味着用于Chrome浏览器调查的取证技术也适用于Edge。 …

python学智能算法(八)|决策树

【1】引言 前序学习进程中&#xff0c;已经对KNN邻近算法有了探索&#xff0c;相关文章链接为&#xff1a; python学智能算法&#xff08;七&#xff09;|KNN邻近算法-CSDN博客 但KNN邻近算法有一个特点是&#xff1a;它在分类的时候&#xff0c;不能知晓每个类别内事物的具…

RTSP/Onvif安防监控系统EasyNVR级联视频上云系统EasyNVS报错“Login error”的原因排查与解决

EasyNVR安防视频云平台是旭帆科技TSINGSEE青犀旗下支持RTSP/Onvif协议接入的安防监控流媒体视频云平台。平台具备视频实时监控直播、云端录像、云存储、录像检索与回看、告警等视频能力&#xff0c;能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、W…

通信网络安全防护定级备案需要材料汇总

通信网络安全防护定级备案工作需要到指定的系统上先写基本信息&#xff0c;然后上传对应的材料&#xff0c;提交后会流转到地方通管局或部里审核。对于第一次使用该系统的朋友来说&#xff0c;通信网络安全防护定级备案需要什么材料是目前比较关注的问题。下面calm13就结合以往…

15:00面试,15:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到8月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…