Java配列に含めることができる要素の数に制限はありますか?もしそうなら、それは何ですか?
Java配列に含めることができる要素の数に制限はありますか?もしそうなら、それは何ですか?
回答:
テストは非常に簡単ですが、正しい答えを見ていません。
最近のHotSpot VMでは、正解はInteger.MAX_VALUE - 5
です。それを超えると:
public class Foo {
public static void main(String[] args) {
Object[] array = new Object[Integer.MAX_VALUE - 4];
}
}
あなたが得る:
Exception in thread "main" java.lang.OutOfMemoryError:
Requested array size exceeds VM limit
MAX_VALUE-2
要素まで割り当てることができます。これは、何を割り当てるかとは無関係であり、VMが2つの「もの」を何に使用できるのか本当に疑問です(長さが2バイトに収まりません)。
Integer.MAX_VALUE+1
は、整数オーバーフローが発生します。Javaの配列サイズはint
でありlong
、ではありません。配列、バイト、または参照に格納するデータ型に関係なく。文字列は単なるオブジェクト参照です。
Integer.MAX_VALUE - 2
= 2 147 483 645です。Javaをで実行すると、Javaはそのような配列を正常に割り当てます-Xmx13G
。OutOfMemoryError: Java heap space
合格すると失敗します-Xmx12G
。
これは(もちろん)完全にVMに依存します。
OpenJDKの7と8のソースコードを閲覧java.util.ArrayList
、.Hashtable
、.AbstractCollection
、 .PriorityQueue
、そして.Vector
、あなたはこれを参照することができます主張が繰り返されています:
/** * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
これは、Martin Buchholz(Google)によって2010-05-09に追加されました。Chris Hegarty(Oracle)によるレビュー。
したがって、 おそらく 「安全な」最大数は2 147 483 639(Integer.MAX_VALUE - 8
)であり、「より大きな配列を割り当てようとするとOutOfMemoryErrorが発生する可能性がある」と言え ます。
(はい、ブッフホルツの独立した主張には裏付けとなる証拠が含まれていないため、これは権威にとって計算上魅力的です。OpenJDK内でも、まだ実際に使用されていないreturn (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
ことを示すようなコードを見ることができます。)MAX_ARRAY_SIZE
-8
ですか?
-8
ため、予約されたヘッダーワードが占めるバイト数が原因です。
実際には2つの制限があります。1つは配列のインデックス可能な最大要素、2つはアプリケーションで使用可能なメモリの量です。使用可能なメモリ量と他のデータ構造で使用される量によっては、アドレス指定可能な最大配列要素に達する前にメモリ制限に達する場合があります。
この記事を読むhttp://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays:
Javaは2 31 -1(約21億)を超える要素の配列をサポートしないことで批判されています。これは言語の制限です。Java言語仕様のセクション10.4では、次のように述べています。
配列にはint値でインデックスを付ける必要があります...長いインデックス値で配列コンポーネントにアクセスしようとすると、コンパイル時エラーが発生します。
大きな配列をサポートするには、JVMを変更する必要もあります。この制限は、コレクションが20億要素に制限されていたり、2 GiBを超えるメモリマップファイルを作成できないなどの領域で明らかになります。また、Javaには、科学的および技術的コンピューティングのパフォーマンスを制限する真の多次元配列(単一の間接参照によってアクセスされるメモリの連続的に割り当てられた単一のブロック)がありません。
配列には負でない整数のインデックスが付けられているため、アクセスできる配列の最大サイズはになりますInteger.MAX_VALUE
。もう1つは、作成できる配列の大きさです。使用可能な最大メモリJVM
と配列のコンテンツタイプによって異なります。たとえば、各配列要素にはサイズがあります。byte = 1 byte
、int = 4 bytes
、Object reference = 4 bytes (on a 32 bit system)
したがって1 MB
、マシンで使用可能なメモリがある場合は、byte[1024 * 1024]
またはの配列を割り当てることができますObject[256 * 1024]
。
あなたの質問に答える -あなたはサイズの配列を割り当てることができます(利用可能な最大メモリ/配列項目のサイズ)。
概要 -理論的には、配列の最大サイズはになりますInteger.MAX_VALUE
。実際には、メモリのJVM
量と、他のオブジェクトにすでに割り当てられているメモリの量によって異なります。
このようなバイト配列を作成してみました
byte[] bytes = new byte[Integer.MAX_VALUE-x];
System.out.println(bytes.length);
この実行構成では:
-Xms4G -Xmx4G
そしてjavaバージョン:
Openjdkバージョン「1.8.0_141」
OpenJDKランタイム環境(ビルド1.8.0_141-b16)
OpenJDK 64ビットサーバーVM(ビルド25.141-b16、混合モード)
x> = 2の場合にのみ機能します。つまり、配列の最大サイズはInteger.MAX_VALUE-2です。
上記の値は
スレッド「main」の例外java.lang.OutOfMemoryError:リクエストされた配列サイズがMain.main(Main.java:6)でVMの制限を超えています
実際には、Javaの制限で、2 ^ 30-4を1073741820に制限しています。2^ 31-1ではありません。Dunno理由ですが、jdkで手動でテストしました。2 ^ 30-3は例外としてVMをスローしています
編集:-1から-4に修正、Windows jvmでチェック