自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java中的String到底占用多大的內(nèi)存空間?你所了解的可能都是錯誤的?。?/h1>

存儲 存儲軟件 后端
作者個人研發(fā)的在高并發(fā)場景下,提供的簡單、穩(wěn)定、可擴(kuò)展的延遲消息隊列框架,具有精準(zhǔn)的定時任務(wù)和延遲隊列處理功能。

[[347440]]

 作者個人研發(fā)的在高并發(fā)場景下,提供的簡單、穩(wěn)定、可擴(kuò)展的延遲消息隊列框架,具有精準(zhǔn)的定時任務(wù)和延遲隊列處理功能。自開源半年多以來,已成功為十幾家中小型企業(yè)提供了精準(zhǔn)定時調(diào)度方案,經(jīng)受住了生產(chǎn)環(huán)境的考驗。為使更多童鞋受益,現(xiàn)給出開源框架地址:https://github.com/sunshinelyz/mykit-delay

寫在前面

最近小伙伴加群時,我總是問一個問題:Java中的String類占用多大的內(nèi)存空間?很多小伙伴的回答著實讓我哭笑不得,有說不占空間的,有說1個字節(jié)的,有說2個字節(jié)的,有說3個字節(jié)的,有說不知道的,更讓人哭笑不得的是竟然還有人說是2的31次方。那如果真是這樣的話,服務(wù)器的內(nèi)存空間還放不下一個字符串呀!作為程序員的我們,可不能鬧這種笑話呀。今天,我們就一起來聊聊Java中的String到底占用多大的內(nèi)存空間!

Java對象的結(jié)構(gòu)

首先,我們來下Java對象在虛擬機(jī)中的結(jié)構(gòu),這里,以HotSpot虛擬機(jī)為例。

注:圖片來源http://r6d.cn/wp7q

從上面的這張圖里面可以看出,對象在內(nèi)存中的結(jié)構(gòu)主要包含以下幾個部分:

  • Mark Word(標(biāo)記字段):對象的Mark Word部分占4個字節(jié),其內(nèi)容是一系列的標(biāo)記位,比如輕量級鎖的標(biāo)記位,偏向鎖標(biāo)記位等等。
  • Klass Pointer(Class對象指針):Class對象指針的大小也是4個字節(jié),其指向的位置是對象對應(yīng)的Class對象(其對應(yīng)的元數(shù)據(jù)對象)的內(nèi)存地址
  • 對象實際數(shù)據(jù):這里面包括了對象的所有成員變量,其大小由各個成員變量的大小決定,比如:byte和boolean是1個字節(jié),short和char是2個字節(jié),int和float是4個字節(jié),long和double是8個字節(jié),reference是4個字節(jié)
  • 對齊:最后一部分是對齊填充的字節(jié),按8個字節(jié)填充。

換種說法就是:

  • 對象頭(object header):8 個字節(jié)(保存對象的 class 信息、ID、在虛擬機(jī)中的狀態(tài))
  • Java 原始類型數(shù)據(jù):如 int, float, char 等類型的數(shù)據(jù)
  • 引用(reference):4 個字節(jié)
  • 填充符(padding)

Java中的String類型

空String占用的空間

這里,我們以Java8為例進(jìn)行說明。首先,我們來看看String類中的成員變量。

  1. /** The value is used for character storage. */ 
  2. private final char value[]; 
  3.   
  4. /** Cache the hash code for the string */ 
  5. private int hash; // Default to 0 
  6.   
  7. /** use serialVersionUID from JDK 1.0.2 for interoperability */ 
  8. private static final long serialVersionUID = -6849794470754667710L; 

在 Java 里數(shù)組也是對象,因此數(shù)組也有對象頭。所以,一個數(shù)組所占的空間為對象頭所占的空間加上數(shù)組長度加上數(shù)組的引用,即 8 + 4 + 4= 16 字節(jié) 。

所以,我們可以得出一個空String對象所占用的內(nèi)存空間,如下所示。

  1. 對象頭(8 字節(jié))+ 引用 (4 字節(jié) )  + char 數(shù)組(16 字節(jié))+ 1個 int(4字節(jié))+ 1個long(8字節(jié))= 40 字節(jié) 

所以,小伙伴們,你們的回答正確嗎?

非空String占用的空間

如果String字符串的長度大于0的話,我們也可以得出String占用內(nèi)存的計算公式,如下所示。

  1. 40 + 2 * n 

其中,n為字符串的長度。

這里,可能有小伙伴會問,為什么是 40 + 2 * n 呢?這是因為40是空字符串占用的內(nèi)存空間,這個我們上面已經(jīng)說過了,String類實際上是把數(shù)據(jù)存儲到char[]這個成員變量數(shù)組中的,而char[]數(shù)組中的一個char類型的數(shù)據(jù)占用2個字節(jié)的空間,所以,只是String中的數(shù)據(jù)就會占用 2 * n(n為字符串的長度)個字節(jié)的空間,再加上空字符串所占用的40個字節(jié)空間,最終得出一個字符串所占用的存儲空間為:40 + 2 * n (n為字符串長度)。

因此在代碼中大量使用String對象時,應(yīng)考慮內(nèi)存的實際占用情況。

注:40 + 2 * n 這個公式我們可以看成是計算String對象占用多大內(nèi)存空間的通用公式。

驗證結(jié)論

接下來,我們就一起來驗證下我們上面的結(jié)論。首先,創(chuàng)建一個UUIDUtils類用來生成32位的UUID,如下所示。

  1. package io.mykit.binghe.string.test; 
  2.  
  3. import java.util.UUID; 
  4.  
  5. /** 
  6.  * @author binghe 
  7.  * @version 1.0.0 
  8.  * @description 生成沒有-的UUID 
  9.  */ 
  10. public class UUIDUtils { 
  11.  public static String getUUID(){ 
  12.   String uuid = UUID.randomUUID().toString(); 
  13.   return uuid.replace("-"""); 
  14.  } 

接下來,創(chuàng)建一個TestString類,在main()方法中創(chuàng)建一個長度為4000000的數(shù)組,然后在數(shù)組中放滿UUID字符串,如下所示。

  1. package io.mykit.binghe.string.test; 
  2.  
  3. import java.util.UUID; 
  4.  
  5. /** 
  6.  * @author binghe 
  7.  * @version 1.0.0 
  8.  * @description 測試String占用的內(nèi)存空間 
  9.  */ 
  10. public class TestString{ 
  11.     public static void main(String[] args){ 
  12.          String[] strContainer = new String[4000000]; 
  13.         for(int i = 0; i < 4000000; i++){ 
  14.             strContainer[i] = UUIDUtils.getUUID(); 
  15.             System.out.println(i); 
  16.         } 
  17.         //防止程序退出 
  18.         while(true){ 
  19.  
  20.         } 
  21.     } 

這里,4000000個字符串,每個字符串的長度為32,所以保存字符串?dāng)?shù)據(jù)所占用的內(nèi)存空間為:(40 + 32 * 2) * 4000000 = 416000000字節(jié),約等于416MB。

我們使用Jprofiler內(nèi)存分析工具進(jìn)行分析:

可以看到,使用Jprofiler內(nèi)存分析工具的結(jié)果為:321MB + 96632KB,約等于417MB。之所以使用Jprofiler內(nèi)存分析工具得出的結(jié)果比我們計算的大些,是因為在程序?qū)嶋H運(yùn)行的過程中,程序內(nèi)部也會生成一些字符串,這些字符串也會占用內(nèi)存空間!!

所以,使用Jprofiler內(nèi)存分析工具得出的結(jié)果符合我們的預(yù)期。

本文轉(zhuǎn)載自微信公眾號「冰河技術(shù)」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系冰河技術(shù)公眾號。

 

責(zé)任編輯:武曉燕 來源: 冰河技術(shù)
相關(guān)推薦

2021-08-21 15:11:31

微信內(nèi)存功能

2023-09-02 21:31:16

Java內(nèi)存泄漏

2013-10-21 17:57:54

2021-02-26 13:35:46

JavaCPU內(nèi)存

2018-05-18 08:43:27

Linux內(nèi)存空間

2020-08-17 17:47:30

內(nèi)存技術(shù)測試

2018-07-16 09:00:32

LinuxBash數(shù)組

2017-03-13 17:25:00

移動支付技術(shù)支撐易寶

2023-10-26 07:09:30

Golangrune字符

2021-01-01 09:05:50

java編碼亂碼

2019-11-21 15:08:13

DevOps云計算管理

2024-01-08 08:42:43

2020-07-24 10:14:17

網(wǎng)絡(luò)安全黑客技術(shù)

2020-03-02 14:55:02

JavaBigDecimalAPI

2020-10-21 09:28:25

JS變量的內(nèi)存分配

2019-04-03 09:10:35

Rediskey-value數(shù)據(jù)庫

2013-11-11 10:07:43

靜態(tài)路由配置

2009-09-07 09:10:24

Windows 7占用空間

2017-11-17 06:06:23

交換機(jī)ASIC路由器

2023-10-26 11:19:21

指針Go
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號