JavaのStringはどのくらいのメモリスペースを占有しますか?ステップバイステップの検証を行います!

前に書く

最近、私はいつも質問をします:JavaのStringクラスはどのくらいのメモリスペースを占有しますか?友達の答えの多くは本当に私を唖然とさせました。スペースを取らないと言う人もいれば、1バイトと言う人もいれば、2バイトと言う人もいれば、3バイトと言う人もいれば、知らないと言う人もいれば、知らないと言う人もいます。驚かされるのは、2の31乗だと言う人もいるということです。この場合でも、サーバーのメモリスペースは文字列に収まりません。プログラマーとして、私たちはそのような冗談を言うことはできません。今日は、Javaの文字列が占めるメモリスペースについて話しましょう!

Javaの知識やインタビューの質問がもっと必要な友達は、下のリンクをクリックして無料で入手できます。

リンク:1103806531パスワード:CSDN

ここに写真の説明を挿入

Javaオブジェクトの構造

まず、仮想マシンのJavaオブジェクトの構造を見てみましょう。ここでは、例としてHotSpot仮想マシンを取り上げます。

ここに写真の説明を挿入
上の写真からわかるように、メモリ内のオブジェクトの構造には、主に次の部分が含まれています。

  • マークワード(マークフィールド):オブジェクトのマークワード部分は4バイトを占め、その内容は、軽量ロックマークビット、バイアスロックマークビットなどの一連のマークビットです。
  • Klassポインター(クラスオブジェクトポインター):クラスオブジェクトポインターのサイズも4バイトであり、それが指す場所は、オブジェクト(対応するメタデータオブジェクト)に対応するクラスオブジェクトのメモリアドレスです。
  • オブジェクトの実際のデータ:オブジェクトのすべてのメンバー変数が含まれ、そのサイズは各メンバー変数のサイズによって決定されます。たとえば、byteとbooleanは1バイト、shortとcharは2バイト、intとfloatは4です。バイト、ロング、ダブルは8バイト、リファレンスは4バイト
  • 整列:最後の部分は、8バイトで埋められた埋められたバイトを整列することです。

言い換えると:

  • オブジェクトヘッダー:8バイト(オブジェクトのクラス情報、ID、状態を仮想マシンに保存します)
  • Javaプリミティブデータ:int、float、char、その他のタイプのデータなど
  • 参照:4バイト
  • パディング

Javaの文字列タイプ

空の文字列が占めるスペース

ここでは、例としてJava8を取り上げます。まず、Stringクラスのメンバー変数を見てみましょう。

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

配列もJavaのオブジェクトであるため、配列にもオブジェクトヘッダーがあります。したがって、配列が占めるスペースは、オブジェクトヘッダーが占めるスペース、配列の長さ、配列参照、つまり8 + 4 + 4 = 16バイトです。

したがって、以下に示すように、空のStringオブジェクトが占めるメモリスペースを取得できます。

对象头(8 字节)+ 引用 (4 字节 )  + char 数组(16 字节)+ 1int4字节)+ 1long8字节)= 40 字节

それで、私の友達、あなたの答えは正しいですか?

空でない文字列が占めるスペース

String文字列の長さが0より大きい場合、以下に示すように、Stringが占有するメモリの計算式を取得することもできます。

40 + 2 * n

その中で、nは文字列の長さです。

ここで、何人かの友人が尋ねるかもしれません、なぜそれは40 + 2 nですか?これは、40が空の文字列によって占有されるメモリ空間であるためです。すでに述べたように、Stringクラスは実際にはchar []メンバー変数配列にデータを格納し、char []配列にchar型を格納します。データは2バイトのスペースを占有するため、文字列内のデータだけが2 n(nは文字列の長さ)バイトのスペースを占有し、さらに40バイトが空の文字列によって占有されます。最後に、文字列が占めるストレージスペースは40 + 2 * n(nは文字列の長さ)です。

注:式40 + 2 * nは、Stringオブジェクトが占めるメモリスペースの量を計算するための一般的な式と見なすことができます。

したがって、コードで多数のStringオブジェクトが使用されている場合は、実際のメモリ使用量を考慮する必要があります。

検証の結論

次に、上記の結論を一緒に検証します。まず、以下に示すように、UUIDUtilsクラスを作成して32ビットUUIDを生成します。

package io.mykit.binghe.string.test;

import java.util.UUID;

/**
 * @author binghe
 * @version 1.0.0
 * @description 生成没有-的UUID
 */
public class UUIDUtils {
    
    
    public static String getUUID(){
    
    
        String uuid = UUID.randomUUID().toString();
        return uuid.replace("-", "");
    }
}

次に、TestStringクラスを作成し、main()メソッドで長さが4000000の配列を作成してから、次に示すように、配列にUUID文字列を入力します。

package io.mykit.binghe.string.test;

import java.util.UUID;

/**
 * @author binghe
 * @version 1.0.0
 * @description 测试String占用的内存空间
 */
public class TestString{
    
    
    public static void main(String[] args){
    
    
         String[] strContainer = new String[4000000];
        for(int i = 0; i < 4000000; i++){
    
    
            strContainer[i] = UUIDUtils.getUUID();
            System.out.println(i);
        }
        //防止程序退出
        while(true){
    
    

        }
    }
}

ここでは、4000000文字の文字列があり、各文字文字列の長さは32であるため、文字列データを格納するために占有されるメモリスペースは次のようになります。(40 + 32 2)4000000 = 416000000バイト、これは約416MBに相当します。

分析にはJprofilerメモリ分析ツールを使用します。

ここに写真の説明を挿入
ご覧のとおり、Jprofilerメモリ分析ツールを使用した結果は321MB + 96632KBであり、これは417MBにほぼ相当します。Jprofilerメモリ分析ツールを使用して得られた結果が計算よりも大きい理由は、プログラムの実際の実行中に、プログラム内でいくつかの文字列が生成され、これらの文字列もメモリスペースを占有するためです。

したがって、Jprofilerメモリ分析ツールを使用して得られた結果は私たちの期待に応えました。

やっと

また、Javaのコア知識ポイント、インタビュートピック、最新のインターネットの実際の質問や電子書籍など、建築家向けのビデオチュートリアルとJavaに関する体系的な資料のフルセットを20年間編集しました。困っている友達は下のリンクをクリックして無料で入手できます!

リンク:1103806531パスワード:CSDN

ここに写真の説明を挿入
ここに写真の説明を挿入

おすすめ

転載: blog.csdn.net/XingXing_Java/article/details/109250697