อาร์เรย์ Java มีขนาดสูงสุดหรือไม่


214

มีการ จำกัด จำนวนองค์ประกอบที่อาร์เรย์ Java สามารถมีได้หรือไม่? ถ้าเป็นเช่นนั้นมันคืออะไร?


5
คุณยอมรับคำตอบที่ผิดเพียงลองจัดสรรอาเรย์ที่มีขนาดยาว (และไม่ฉันไม่ได้ใช้หน่วยความจำไม่เพียงพอ)
maaartinus

เกี่ยวข้องอย่างใกล้ชิด: stackoverflow.com/questions/878309/…
Ciro Santilli i 冠状病病六四事件法轮功

คำตอบที่ถูกต้องคือstackoverflow.com/questions/31382531/ …
Ivan Mamontov

คำตอบ:


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
ผมคิดว่าความคิดของ downvotes ทำให้รู้สึกไม่เว้นแต่เรายินดีที่จะ downvote คำตอบที่เป็นธรรมดาและก็ไม่ถูกต้อง ความแตกต่างของห้าไบต์มีความสำคัญจริง ๆ หรือไม่ไม่แน่นอน แต่มันเกี่ยวข้องกับฉันว่าผู้คนยินดีที่จะให้คำตอบ "เผด็จการ" โดยไม่ต้องพยายามที่จะดูว่ามันใช้งานได้จริง สำหรับขีด จำกัด ของหน่วยความจำนั้นก็คือ DUH ถ้าคุณถามฉันว่า "คุณกินองุ่นได้กี่ลูก?" และฉันก็พูดว่า "ก็ขึ้นอยู่กับว่าฉันมีอยู่ในตู้เย็นมากแค่ไหนในเวลานั้น"
Kevin Bourrillion

7
คุณรู้หรือไม่ว่าทำไมมันถึงไม่ยอมให้คุณห้าไบต์? นี่เป็นสิ่งที่เกิดขึ้นเสมอใน Java หรืออาจเกี่ยวข้องกับหน่วยความจำของคอมพิวเตอร์ของคุณหรือเปล่า
Taymon

17
@Kevin Bourrillion: สิ่งนี้ดูเหมือนว่าจะมีการเปลี่ยนแปลงโดยใช้ Oracle 1.7.0_07 ฉันสามารถจัดสรรได้ถึงMAX_VALUE-2องค์ประกอบ สิ่งนี้เป็นอิสระจากสิ่งที่ฉันจัดสรรและฉันสงสัยจริงๆว่า VM สามารถใช้ "สองสิ่ง" สำหรับอะไรได้บ้าง (ความยาวไม่พอดีเป็น 2 ไบต์)
maaartinus

3
@ TomášZatoล่าสุดที่Integer.MAX_VALUE+1คุณจะมีจำนวนเต็มล้น ขนาดของอาเรย์ใน Java นั้นintไม่ใช่long; ไม่ว่าคุณจะเก็บข้อมูลประเภทใดไว้ในอาร์เรย์ไบต์หรือการอ้างอิงของคุณ สตริงเป็นเพียงการอ้างอิงวัตถุ
แล้ว - Anony-Mousse

8
จำนวนสูงสุดขององค์ประกอบในอาร์เรย์ใน JDK 6 ขึ้นไปเป็นInteger.MAX_VALUE - 2= 2 147 483 645 Java -Xmx13Gประสบความสำเร็จในการจัดสรรเช่นอาร์เรย์ถ้าคุณใช้มันด้วย มันล้มเหลวด้วยถ้าคุณผ่านOutOfMemoryError: 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 639 ( Integer.MAX_VALUE - 8) และ "ความพยายามที่จะจัดสรรอาร์เรย์ขนาดใหญ่อาจส่งผลให้OutOfMemoryError "

(ใช่การอ้างสิทธิ์แบบสแตนด์อโลนของ Buchholz ไม่รวมถึงหลักฐานการสนับสนุนดังนั้นนี่จึงเป็นคำอุทธรณ์ที่มีการคำนวณถึงผู้มีอำนาจแม้ใน OpenJDK เองเราสามารถดูรหัสreturn (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;ที่แสดงให้เห็นว่าMAX_ARRAY_SIZEยังไม่มีการใช้งานจริง )


และทำไมเราต้องเพิ่ม-8?
JohnWinter

@Pacerier ไม่ควรใช้ MAX_ARRAY_SIZE นี้เฉพาะเมื่อคุณใช้ ArrayList หรือไม่ ซึ่งแตกต่างจากการใช้อาร์เรย์เช่น int [] array = new int [some_value_here]; ไม่ใช่เหรอ ทำไมค่าคงที่ที่กำหนดใน ArrayList สามารถนำไปใช้กับอาร์เรย์ปกติ (กำหนดด้วย []) ได้อย่างไร พวกเขาเหมือนกันเบื้องหลังหรือไม่
Tiago

1
@ ติอาโก้ไม่รหัสตัวเองไม่มีอะไรเกี่ยวข้องกับขนาดสูงสุดของอาร์เรย์ มันเป็นเพียงการเรียกร้อง
Pacerier

@JohnWinter เครื่องหมายคำพูดระบุว่า "VMs บางตัวสงวนคำส่วนหัวบางส่วนไว้ในอาร์เรย์" ดังนั้น-8เนื่องจากไบต์คำส่วนหัวที่สงวนไว้จะครอบครอง
Pacerier

38

จริงๆแล้วมีข้อ จำกัด อยู่สองข้อ หนึ่งองค์ประกอบสูงสุดที่สามารถจัดทำดัชนีสำหรับอาเรย์และสองจำนวนหน่วยความจำที่แอปพลิเคชันของคุณสามารถใช้ได้ ขึ้นอยู่กับจำนวนหน่วยความจำที่มีอยู่และจำนวนที่ใช้โดยโครงสร้างข้อมูลอื่น ๆ คุณอาจถึงขีด จำกัด หน่วยความจำก่อนที่จะถึงองค์ประกอบอาร์เรย์ที่กำหนดแอดเดรสได้สูงสุด


27

ดำเนินการโดยบทความนี้http://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays :

Java ได้รับการวิพากษ์วิจารณ์ว่าไม่ได้สนับสนุนอาเรย์มากกว่า 2 31 −1 (ประมาณ 2.1 พันล้านองค์ประกอบ) นี่เป็นข้อ จำกัด ของภาษา ข้อกำหนดภาษา Java ส่วน 10.4 ระบุว่า:

อาร์เรย์จะต้องจัดทำดัชนีโดยค่า int ... ความพยายามในการเข้าถึงองค์ประกอบอาร์เรย์ที่มีค่าดัชนียาวทำให้เกิดข้อผิดพลาดในการคอมไพล์เวลา

การสนับสนุนอาร์เรย์ขนาดใหญ่จะต้องมีการเปลี่ยนแปลง JVM ด้วย ข้อ จำกัด นี้แสดงออกในพื้นที่เช่นคอลเลกชันที่ถูก จำกัด องค์ประกอบ 2 พันล้านและไม่สามารถแมปไฟล์หน่วยความจำที่มีขนาดใหญ่กว่า 2 GiB Java ยังขาดอาร์เรย์หลายมิติที่แท้จริง (จัดสรรหน่วยความจำบล็อกเดียวอย่างต่อเนื่องที่เข้าถึงได้โดยการอ้อมเพียงครั้งเดียว) ซึ่ง จำกัด ประสิทธิภาพสำหรับการคำนวณทางวิทยาศาสตร์และทางเทคนิค


6
Java ไม่มีน้ำตาลประโยคสำหรับอาร์เรย์หลายมิติ แต่คุณยังสามารถ "มี" พวกเขาด้วยการคูณเล็กน้อย (ยกเว้นขนาดรวมของอาร์เรย์เกินขีด จำกัด ดังกล่าวข้างต้น)
kbolino

11

Integer.MAX_VALUEอาร์เรย์เป็นจำนวนเต็มไม่เป็นลบการจัดทำดัชนีขนาดอาร์เรย์สูงสุดเพื่อให้คุณสามารถเข้าถึงจะ อีกอย่างคือขนาดของอาร์เรย์ที่คุณสามารถสร้างได้ ขึ้นอยู่กับหน่วยความจำสูงสุดที่คุณมี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และจำนวนหน่วยความจำที่จัดสรรให้กับวัตถุอื่นแล้ว


3

ฉันพยายามสร้างอาร์เรย์แบบนี้

byte[] bytes = new byte[Integer.MAX_VALUE-x];
System.out.println(bytes.length);

ด้วยการกำหนดค่าการทำงานนี้:

-Xms4G -Xmx4G

และเวอร์ชันจาวา:

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: ขนาดอาร์เรย์ที่ร้องขอเกินขีด จำกัด VM ที่ Main.main (Main.java:6)


2

ใช่มีข้อ จำกัด เกี่ยวกับอาร์เรย์ java Java ใช้จำนวนเต็มเป็นดัชนีไปยังอาร์เรย์และที่เก็บจำนวนเต็มสูงสุดโดย JVM คือ 2 ^ 32 เพื่อให้คุณสามารถเก็บองค์ประกอบ 2,147,483,647 องค์ประกอบในอาร์เรย์

ในกรณีที่คุณต้องการมากกว่าความยาวสูงสุดคุณสามารถใช้สองอาร์เรย์ที่แตกต่างกัน แต่วิธีที่แนะนำคือเก็บข้อมูลไว้ในไฟล์ เนื่องจากการจัดเก็บข้อมูลในไฟล์ไม่มีข้อ จำกัด เนื่องจากไฟล์ที่เก็บไว้ในไดรเวอร์อุปกรณ์เก็บข้อมูลของคุณ แต่อาร์เรย์จะถูกเก็บไว้ใน JVM JVM จัดเตรียมพื้นที่ จำกัด สำหรับการเรียกใช้โปรแกรม


1

จำนวนองค์ประกอบสูงสุดของarrayคือ(2^31)−1หรือ2 147 483 647


5
Java ไม่สามารถจัดสรรขนาดอาร์เรย์Integer.MAX_VALUE - 1ได้คุณจะได้รับ "java.lang.OutOfMemoryError: ขนาดอาร์เรย์ที่ร้องขอเกินขีด จำกัด VM" จำนวนสูงสุดขององค์ประกอบใน JDK 6 ขึ้นไปคือInteger.MAX_VALUE - 2= 2 147 483 645
Alexey Ivanov

0

จริงๆแล้วมันเป็นข้อ จำกัด ของจาวาที่ขีดที่ 2 ^ 30-4 เป็น 1073741820 ไม่ใช่ 2 ^ 31-1 Dunno ทำไม แต่ฉันทดสอบด้วยตนเองใน jdk 2 ^ 30-3 ยังคงขว้าง vm ยกเว้น

แก้ไข: แก้ไข -1 ถึง -4, ตรวจสอบบน windows jvm


คุณกำลังใช้ JVM 32 บิต ใช้ JVM 64 บิตและขีด จำกัด JVM จะใกล้เคียงกับ 2 ^ 31 (คุณต้องมีพื้นที่ว่างให้ใช้งานซึ่งไม่ได้เป็นค่าเริ่มต้นและจะได้รับผลกระทบจากหน่วยความจำกายภาพของคุณ)
dave_thompson_085
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.