これは Sun JDK 1.6u21、x64 です。
単一の大きな文字列 (512k 文字) のみを含む perm gen の使用法を試すためのクラスがあります。
public class Big0 {
public String bigString =
"A string with 2^19 characters, should be 1 MB in size";
}
perm gen の使用状況を、パーマネント生成用getUsage().toString()
のMemoryPoolMXBean
オブジェクト (u21 では「PS Perm Gen」と呼ばれますが、バージョンやガベージ コレクターによって若干異なりますが) を使用して確認します。
クラスを最初に参照すると、たとえば を読んBig0.class
で、 perm gen が最大 500 KB ジャンプします。これは、文字列の定数プール エンコーディングが UTF-8 であり、ASCII 文字のみを使用しているためです。
ただし、実際にこのクラスのインスタンスを作成すると、perm gen が約 2 MB ジャンプします。これはメモリ内の 1 MB の文字列 (UTF16 文字ごとに 2 バイト、確かにサロゲートなし) であるため、メモリ使用量が 2 倍になる理由について混乱しています。
文字列を静的にすると、同じ効果が発生します。final を使用した場合、65535 バイトの定数プール項目の制限を超えるため、コンパイルに失敗します (なぜ final をオフのままにしておくとそれが回避されるのかわかりません - それはおまけの質問と考えてください)。
どんな洞察も大歓迎です!
編集:これは、非静的、最終非静的、および静的文字列で発生しますが、最終静的文字列では発生しないことも指摘する必要があります。これはすでに文字列定数のベスト プラクティスであるため、おそらくこれは主に学術的な関心事です。