电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

一個Java對象到底占多大內存?

瀏覽:88日期:2022-09-06 09:21:43

最近在讀《深入理解Java虛擬機》,對Java對象的內存布局有了進一步的認識,于是腦子里自然而然就有一個很普通的問題,就是一個Java對象到底占用多大內存?

在網上搜到了一篇博客講的非常好:http://yueyemaitian.iteye.com/blog/2033046,里面提供的這個類也非常實用:

import java.lang.instrument.Instrumentation; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayDeque; import java.util.Deque; import java.util.HashSet; import java.util.Set; /** * 對象占用字節大小工具類 * * @author tianmai.fh * @date 2014-03-18 11:29 */ public class SizeOfObject { static Instrumentation inst;public static void premain(String args, Instrumentation instP) { inst = instP; }/** * 直接計算當前對象占用空間大小,包括當前類及超類的基本類型實例字段大小、<br></br> * 引用類型實例字段引用大小、實例基本類型數組總占用空間、實例引用類型數組引用本身占用空間大小;<br></br> * 但是不包括超類繼承下來的和當前類聲明的實例引用字段的對象本身的大小、實例引用數組引用的對象本身的大小 <br></br> * * @param obj * @return */ public static long sizeOf(Object obj) { return inst.getObjectSize(obj); }/** * 遞歸計算當前對象占用空間總大小,包括當前類和超類的實例字段大小以及實例字段引用對象大小 * * @param objP * @return * @throws IllegalAccessException */ public static long fullSizeOf(Object objP) throws IllegalAccessException { Set<Object> visited = new HashSet<Object>(); Deque<Object> toBeQueue = new ArrayDeque<Object>(); toBeQueue.add(objP); long size = 0L; while (toBeQueue.size() > 0) { Object obj = toBeQueue.poll(); //sizeOf的時候已經計基本類型和引用的長度,包括數組 size += skipObject(visited, obj) ? 0L : sizeOf(obj); Class<?> tmpObjClass = obj.getClass(); if (tmpObjClass.isArray()) { //[I , [F 基本類型名字長度是2 if (tmpObjClass.getName().length() > 2) { for (int i = 0, len = Array.getLength(obj); i < len; i++) { Object tmp = Array.get(obj, i); if (tmp != null) { //非基本類型需要深度遍歷其對象 toBeQueue.add(Array.get(obj, i)); } } } } else { while (tmpObjClass != null) { Field[] fields = tmpObjClass.getDeclaredFields(); for (Field field : fields) { if (Modifier.isStatic(field.getModifiers()) //靜態不計 || field.getType().isPrimitive()) { //基本類型不重復計 continue; } field.setAccessible(true); Object fieldValue = field.get(obj); if (fieldValue == null) { continue; } toBeQueue.add(fieldValue); } tmpObjClass = tmpObjClass.getSuperclass(); } } } return size; }/** * String.intern的對象不計;計算過的不計,也避免死循環 * * @param visited * @param obj * @return */ static boolean skipObject(Set<Object> visited, Object obj) { if (obj instanceof String && obj == ((String) obj).intern()) { return true; } return visited.contains(obj); } }

大家可以用這個代碼邊看邊驗證,注意的是,運行這個程序需要通過javaagent注入Instrumentation,具體可以看原博客。我今天主要是總結下手動計算Java對象占用字節數的基本規則,做為基本的技能必須get√,希望能幫到和我一樣的Java菜鳥。

在介紹之前,簡單回顧下,Java對象的內存布局:對象頭(Header),實例數據(Instance Data)和對齊填充(Padding),詳細的可以看我的讀書筆記。另外:不同的環境結果可能有差異,我所在的環境是HotSpot虛擬機,64位Windwos。

下面進入正文:

對象頭

對象頭在32位系統上占用8bytes,64位系統上占用16bytes。

一個Java對象到底占多大內存?

一個Java對象到底占多大內存?

實例數據

原生類型(primitive type)的內存占用如下:

Primitive TypeMemory Required(bytes)boolean1byte1short2char2int4float4long8double8

reference類型在32位系統上每個占用4bytes, 在64位系統上每個占用8bytes。

對齊填充

HotSpot的對齊方式為8字節對齊:

(對象頭 + 實例數據 + padding) % 8等于0且0 <= padding < 8

指針壓縮

對象占用的內存大小收到VM參數UseCompressedOops的影響。

1)對對象頭的影響

開啟(-XX:+UseCompressedOops)對象頭大小為12bytes(64位機器)。

static class A {int a; }

A對象占用內存情況:

關閉指針壓縮: 16+4=20不是8的倍數,所以+padding/4=24

一個Java對象到底占多大內存?

開啟指針壓縮: 12+4=16已經是8的倍數了,不需要再padding。

一個Java對象到底占多大內存?

2) 對reference類型的影響

64位機器上reference類型占用8個字節,開啟指針壓縮后占用4個字節。

static class B2 {int b2a;Integer b2b;}

B2對象占用內存情況:

關閉指針壓縮: 16+4+8=28不是8的倍數,所以+padding/4=32

一個Java對象到底占多大內存?

開啟指針壓縮: 12+4+4=20不是8的倍數,所以+padding/4=24

一個Java對象到底占多大內存?

數組對象

64位機器上,數組對象的對象頭占用24個字節,啟用壓縮之后占用16個字節。之所以比普通對象占用內存多是因為需要額外的空間存儲數組的長度。

先考慮下new Integer[0]占用的內存大小,長度為0,即是對象頭的大小:

未開啟壓縮:24bytes

一個Java對象到底占多大內存?

開啟壓縮后:16bytes

一個Java對象到底占多大內存?

接著計算new Integer[1],new Integer[2],new Integer[3]和new Integer[4]就很容易了:

未開啟壓縮:

一個Java對象到底占多大內存?

開啟壓縮:

一個Java對象到底占多大內存?

拿new Integer[3]來具體解釋下:

未開啟壓縮:24(對象頭)+8*3=48,不需要padding;

開啟壓縮:16(對象頭)+3*4=28,+padding/4=32,其他依次類推。

自定義類的數組也是一樣的,比如:

static class B3 {int a;Integer b; }

new B3[3]占用的內存大小:

未開啟壓縮:48

開啟壓縮后:32

復合對象

計算復合對象占用內存的大小其實就是運用上面幾條規則,只是麻煩點。

1)對象本身的大小

直接計算當前對象占用空間大小,包括當前類及超類的基本類型實例字段大小、引用類型實例字段引用大小、實例基本類型數組總占用空間、實例引用類型數組引用本身占用空間大小; 但是不包括超類繼承下來的和當前類聲明的實例引用字段的對象本身的大小、實例引用數組引用的對象本身的大小。

static class B {int a;int b; }static class C {int ba;B[] as = new B[3];C() { for (int i = 0; i < as.length; i++) {as[i] = new B(); }} }

未開啟壓縮:16(對象頭)+4(ba)+8(as引用的大小)+padding/4=32

開啟壓縮:12+4+4+padding/4=24

2)當前對象占用的空間總大小

遞歸計算當前對象占用空間總大小,包括當前類和超類的實例字段大小以及實例字段引用對象大小。

遞歸計算復合對象占用的內存的時候需要注意的是:對齊填充是以每個對象為單位進行的,看下面這個圖就很容易明白。

一個Java對象到底占多大內存?

現在我們來手動計算下C對象占用的全部內存是多少,主要是三部分構成:C對象本身的大小+數組對象的大小+B對象的大小。

未開啟壓縮:

(16 + 4 + 8+4(padding)) + (24+ 8*3) +(16+8)*3 = 152bytes

開啟壓縮:

(12 + 4 + 4 +4(padding)) + (16 + 4*3 +4(數組對象padding)) + (12+8+4(B對象padding))*3= 128bytes

大家有興趣的可以試試。

實際工作中真正需要手動計算對象大小的場景應該很少,但是個人覺得做為基礎知識每個Java開發人員都應該了解,另外:對自己寫的代碼大概占用多少內存,內存中是怎么布局的應該有一個直覺性的認識。

標簽: Java
相關文章:
主站蜘蛛池模板: 自动记录数据电子台秤,记忆储存重量电子桌称,设定时间记录电子秤-昆山巨天 | 球磨机 选矿球磨机 棒磨机 浮选机 分级机 选矿设备厂家 | 南京试剂|化学试剂|分析试剂|实验试剂|cas号查询-专业60年试剂销售企业 | 船用锚链|专业锚链生产厂家|安徽亚太锚链制造有限公司 | 消泡剂_水处理消泡剂_切削液消泡剂_涂料消泡剂_有机硅消泡剂_广州中万新材料生产厂家 | 乐之康护 - 专业护工服务平台,提供医院陪护-居家照护-居家康复 | 塑胶跑道_学校塑胶跑道_塑胶球场_运动场材料厂家_中国塑胶跑道十大生产厂家_混合型塑胶跑道_透气型塑胶跑道-广东绿晨体育设施有限公司 | 植筋胶-粘钢胶-碳纤维布-碳纤维板-环氧砂浆-加固材料生产厂家-上海巧力建筑科技有限公司 | 脉冲除尘器,除尘器厂家-淄博机械 | 上海办公室装修公司_办公室设计_直营办公装修-羚志悦装 | 生产加气砖设备厂家很多,杜甫机械加气砖设备价格公道 | 润滑油加盟_润滑油厂家_润滑油品牌-深圳市沃丹润滑科技有限公司 琉璃瓦-琉璃瓦厂家-安徽盛阳新型建材科技有限公司 | 广州展台特装搭建商|特装展位设计搭建|展会特装搭建|特装展台制作设计|展览特装公司 | 媒介云-全网整合营销_成都新闻媒体发稿_软文发布平台 | 304不锈钢无缝管_不锈钢管厂家 - 隆达钢业集团有限公司 | AR开发公司_AR增强现实_AR工业_AR巡检|上海集英科技 | elisa试剂盒价格-酶联免疫试剂盒-猪elisa试剂盒-上海恒远生物科技有限公司 | 美国查特CHART MVE液氮罐_查特杜瓦瓶_制造全球品质液氮罐 | 液压升降平台_剪叉式液压/导轨式升降机_传菜机定做「宁波日腾升降机厂家」 | 济南展厅设计施工_数字化展厅策划设计施工公司_山东锐尚文化传播有限公司 | 控显科技 - 工控一体机、工业显示器、工业平板电脑源头厂家 | 生物颗粒燃烧机-生物质燃烧机-热风炉-生物颗粒蒸汽发生器-丽水市久凯能源设备有限公司 | 防爆鼓风机-全风-宏丰鼓风机-上海梁瑾机电设备有限公司 | China plate rolling machine manufacturer,cone rolling machine-Saint Fighter | 山东信蓝建设有限公司官网 | 农业四情_农业气象站_田间小型气象站_智慧农业气象站-山东风途物联网 | 护腰带生产厂家_磁石_医用_热压护腰_登山护膝_背姿矫正带_保健护具_医疗护具-衡水港盛 | 净化车间装修_合肥厂房无尘室设计_合肥工厂洁净工程装修公司-安徽盛世和居装饰 | 游戏版号转让_游戏资质出售_游戏公司转让-【八九买卖网】 | 西门子伺服电机维修,西门子电源模块维修,西门子驱动模块维修-上海渠利 | 螺纹三通快插接头-弯通快插接头-宁波舜驰气动科技有限公司 | 安徽泰科检测科技有限公司【官方网站】 | 阿尔法-MDR2000无转子硫化仪-STM566 SATRA拉力试验机-青岛阿尔法仪器有限公司 | 红酒招商加盟-葡萄酒加盟-进口红酒代理-青岛枞木酒业有限公司 | 消泡剂-水处理消泡剂-涂料消泡剂-切削液消泡剂价格-东莞德丰消泡剂厂家 | 液氮罐_液氮容器_自增压液氮罐_杜瓦瓶_班德液氮罐厂家 | 火锅加盟_四川成都火锅店加盟_中国火锅连锁品牌十强_朝天门火锅【官网】 | sfp光模块,高速万兆光模块工厂-性价比更高的光纤模块制造商-武汉恒泰通 | led全彩屏-室内|学校|展厅|p3|户外|会议室|圆柱|p2.5LED显示屏-LED显示屏价格-LED互动地砖屏_蕙宇屏科技 | 苏州柯瑞德货架-仓库自动化改造解决方案 | 哈尔滨京科脑康神经内科医院-哈尔滨治疗头痛医院-哈尔滨治疗癫痫康复医院 |