前に書く
最近、私はいつも質問をします: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 字节)+ 1个 int(4字节)+ 1个long(8字节)= 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