Java配列には最大サイズがありますか?


214

Java配列に含めることができる要素の数に制限はありますか?もしそうなら、それは何ですか?


5
あなたは間違った答えを受け入れました、そのような長い配列を割り当ててみてください(そして、いいえ、私はメモリ不足ではありません)。
maaartinus 2012


回答:


184

テストは非常に簡単ですが、正しい答えを見ていません。

最近の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

57
明白で単純に間違っている回答に反対票を投じない限り、反対投票の考えは意味がないと思います。5バイトの違いは実際には重要ではありませんか、もちろん違います。しかし、それが実際に機能するかどうかを確認することさえせずに、人々が「権威ある」答えを喜んで与えることを心配しています。メモリ制限については、まあ、DUH。「ぶどうはいくつ食べられますか?」と聞いたような感じです。そして、私は「まあ、それは私が冷蔵庫の中に何人持っているかによります」と言いました。
Kevin Bourrillion、

7
それがなぜあなたにそれらの5バイトを与えないの知っいますか?これは必ずしもJavaで常に発生するものですか、それともコンピュータのメモリなどに関連しているだけですか?
Taymon

17
@Kevin Bourrillion:これは変わったようです。Oracle1.7.0_07を使用すると、MAX_VALUE-2要素まで割り当てることができます。これは、何を割り当てるかとは無関係であり、VMが2つの「もの」を何に使用できるのか本当に疑問です(長さが2バイトに収まりません)。
maaartinus 2012

3
@TomášZatoの最新バージョンでInteger.MAX_VALUE+1は、整数オーバーフローが発生します。Javaの配列サイズはintでありlong、ではありません。配列、バイト、または参照に格納するデータ型に関係なく。文字列は単なるオブジェクト参照です。
QUITあり-Anony-Mousse 2014年

8
JDK 6以降の配列の要素の最大数はInteger.MAX_VALUE - 2= 2 147 483 645です。Javaをで実行すると、Javaはそのような配列を正常に割り当てます-Xmx13GOutOfMemoryError: Java heap space合格すると失敗します-Xmx12G
Alexey Ivanov

127

これは(もちろん)完全に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 639Integer.MAX_VALUE - 8)であり、「より大きな配列を割り当てようとするとOutOfMemoryErrorが発生する可能性がある」と言え ます。

(はい、ブッフホルツの独立した主張には裏付けとなる証拠が含まれていないため、これは権威にとって計算上魅力的です。OpenJDK内でも、まだ実際に使用されていないreturn (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;ことを示すようなコードを見ることができます。)MAX_ARRAY_SIZE


そして、なぜ追加する必要があるの-8ですか?
JohnWinter 2015

@Pacerier。このMAX_ARRAY_SIZEは、ArrayListを使用している場合にのみ適用すべきではありませんか?これは、int [] array = new int [some_value_here]のような配列を使用する場合とは異なります。ね?ArrayListで定義された定数を通常の配列([]で定義された)に適用できるのはなぜですか?それらは舞台裏で同じですか?
ティアゴ2015

1
@Tiago、いいえ、コード自体は配列の最大サイズとは関係ありません。それは単なる主張です。
Pacerier 2015年

@JohnWinter、引用は「いくつかのVMは配列内のいくつかのヘッダーワードを予約する」と述べています。その-8ため、予約されたヘッダーワードが占めるバイト数が原因です。
Pacerier 2015年

38

実際には2つの制限があります。1つは配列のインデックス可能な最大要素、2つはアプリケーションで使用可能なメモリの量です。使用可能なメモリ量と他のデータ構造で使用される量によっては、アドレス指定可能な最大配列要素に達する前にメモリ制限に達する場合があります。


27

この記事を読むhttp://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays

Javaは2 31 -1(約21億)を超える要素の配列をサポートしないことで批判されています。これは言語の制限です。Java言語仕様のセクション10.4では、次のように述べています。

配列にはint値でインデックスを付ける必要があります...長いインデックス値で配列コンポーネントにアクセスしようとすると、コンパイル時エラーが発生します。

大きな配列をサポートするには、JVMを変更する必要もあります。この制限は、コレクションが20億要素に制限されていたり、2 GiBを超えるメモリマップファイルを作成できないなどの領域で明らかになります。また、Javaには、科学的および技術的コンピューティングのパフォーマンスを制限する真の多次元配列(単一の間接参照によってアクセスされるメモリの連続的に割り当てられた単一のブロック)がありません。


6
Javaには多次元配列の構文糖はありませんが、少しの乗算で配列を「持つ」ことができます(配列の合計サイズが前述の制限を超えない限り)
kbolino

11

配列には負でない整数のインデックスが付けられているため、アクセスできる配列の最大サイズはになりますInteger.MAX_VALUE。もう1つは、作成できる配列の大きさです。使用可能な最大メモリJVMと配列のコンテンツタイプによって異なります。たとえば、各配列要素にはサイズがあります。byte = 1 byteint = 4 bytesObject reference = 4 bytes (on a 32 bit system)

したがって1 MB、マシンで使用可能なメモリがある場合は、byte[1024 * 1024]またはの配列を割り当てることができますObject[256 * 1024]

あなたの質問に答える -あなたはサイズの配列を割り当てることができます(利用可能な最大メモリ/配列項目のサイズ)。

概要 -理論的には、配列の最大サイズはになりますInteger.MAX_VALUE。実際には、メモリのJVM量と、他のオブジェクトにすでに割り当てられているメモリの量によって異なります。


3

このようなバイト配列を作成してみました

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の制限を超えています


2

はい、Java配列には制限があります。Javaは配列へのインデックスとして整数を使用し、JVMによる最大整数ストアは2 ^ 32です。そのため、配列には2,147,483,647要素を格納できます。

max-lengthを超える長さが必要な場合は、2つの異なる配列を使用できますが、推奨される方法は、データをファイルに格納することです。ファイルにデータを保存するのに制限がないためです。ストレージドライバに格納されているがアレイはJVMに格納されているためです。JVMは、プログラムを実行するための限られたスペースを提供します。


1

要素の最大数arrayであり、(2^31)−1又は2 147 483 647


5
Javaはサイズの配列を割り当てることができませInteger.MAX_VALUE - 1ん。「java.lang.OutOfMemoryError:Requested array size beyond VM limit」と表示されます。最大JDK 6内の要素数以上であるInteger.MAX_VALUE - 2= 2 147 483 645
アレクセイイワノフ

0

実際には、Javaの制限で、2 ^ 30-4を1073741820に制限しています。2^ 31-1ではありません。Dunno理由ですが、jdkで手動でテストしました。2 ^ 30-3は例外としてVMをスローしています

編集:-1から-4に修正、Windows jvmでチェック


32ビットJVMを使用しています。64ビットのJVMを使用すると、JVMの制限は2 ^ 31に近くなります。(また、デフォルトではない使用可能なヒープ・スペースが必要であり、物理メモリーの影響を受けます。)
dave_thompson_085
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.