String
Javaでは(他の言語と同様に)文字ごとに2バイト消費するため、大量のメモリを消費します。そのため、Java 8では、文字列の重複排除これは、char 配列が文字列と final の内部にあるという事実を利用しており、JVM がそれらを操作することができます。
読みましたこの例これまでのところ、私はプロの Java コーダーではないので、概念を理解するのに苦労しています。
そこにはこう書いてある。
文字列の複製にはさまざまな戦略が検討されていますが、現在実装されている戦略は次のアプローチに従います。ガベージ コレクターが文字列オブジェクトにアクセスするたびに、文字配列に注目します。ハッシュ値を取得し、配列への弱参照とともに保存します。同じハッシュ コードを持つ別の文字列が見つかると、文字ごとに比較します。これらも一致する場合、1 つの文字列が変更され、2 番目の文字列の文字配列を指します。最初の文字配列は参照されなくなり、ガベージ コレクションの対象になります。
もちろん、このプロセス全体はいくらかのオーバーヘッドをもたらしますが、厳しい制限によって制御されます。たとえば、文字列に重複がしばらく見つからない場合、その文字列はチェックされなくなります。
私の最初の質問は、
このトピックは Java 8 アップデート 20 で最近追加されたため、まだリソースが不足していますString
。Java で消費されるメモリを削減するのにどのように役立つか、実用的な例を共有していただける方はいらっしゃいますか?
編集:
上記のリンクには、
同じハッシュコードを持つ別の文字列が見つかるとすぐに、それらを文字ごとに比較します。
2つ目の質問は、
2 つのハッシュ コードString
が同じであれば、それらはStrings
すでに同じです。では、2 つのハッシュ コードが同じであることがわかったら、なぜそれらを比較するのchar
でしょうか?char
String
ベストアンサー1
@assylias の回答は、基本的にそれがどのように機能するかを説明しており、非常に良い回答です。私は文字列重複除去を使用して実稼働アプリケーションをテストし、いくつかの結果を得ました。Web アプリは文字列を頻繁に使用するため、利点はかなり明らかだと思います。
文字列重複排除を有効にするには、次の JVM パラメータを追加する必要があります (少なくとも Java 8u20 が必要です)。
-XX:+UseG1GC -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics
最後のはオプションですが、名前の通り、文字列重複除去の統計を表示します。私のものは次のとおりです。
[GC concurrent-string-deduplication, 2893.3K->2672.0B(2890.7K), avg 97.3%, 0.0175148 secs]
[Last Exec: 0.0175148 secs, Idle: 3.2029081 secs, Blocked: 0/0.0000000 secs]
[Inspected: 96613]
[Skipped: 0( 0.0%)]
[Hashed: 96598(100.0%)]
[Known: 2( 0.0%)]
[New: 96611(100.0%) 2893.3K]
[Deduplicated: 96536( 99.9%) 2890.7K( 99.9%)]
[Young: 0( 0.0%) 0.0B( 0.0%)]
[Old: 96536(100.0%) 2890.7K(100.0%)]
[Total Exec: 452/7.6109490 secs, Idle: 452/776.3032184 secs, Blocked: 11/0.0258406 secs]
[Inspected: 27108398]
[Skipped: 0( 0.0%)]
[Hashed: 26828486( 99.0%)]
[Known: 19025( 0.1%)]
[New: 27089373( 99.9%) 823.9M]
[Deduplicated: 26853964( 99.1%) 801.6M( 97.3%)]
[Young: 4732( 0.0%) 171.3K( 0.0%)]
[Old: 26849232(100.0%) 801.4M(100.0%)]
[Table]
[Memory Usage: 2834.7K]
[Size: 65536, Min: 1024, Max: 16777216]
[Entries: 98687, Load: 150.6%, Cached: 415, Added: 252375, Removed: 153688]
[Resize Count: 6, Shrink Threshold: 43690(66.7%), Grow Threshold: 131072(200.0%)]
[Rehash Count: 0, Rehash Threshold: 120, Hash Seed: 0x0]
[Age Threshold: 3]
[Queue]
[Dropped: 0]
これらはアプリを10分間実行した後の結果です。ご覧のとおり、文字列の重複排除が実行されました。452時間と「重複排除」801.6MB文字列。文字列重複排除の検査27 000 000文字列。Java 7の標準並列GCとJava 8u20のG1 GCと文字列重複排除を有効にした場合のメモリ消費量を比較すると、ヒープは約50%:
Java 7 並列 GC
文字列重複排除機能を備えた Java 8 G1 GC