Các mảng Java có kích thước tối đa không?


214

Có giới hạn số lượng phần tử mà mảng Java có thể chứa không? Nếu vậy, nó là cái gì?


5
Bạn đã chấp nhận một câu trả lời sai, chỉ cần cố gắng phân bổ một mảng dài như vậy (và không, tôi không hết bộ nhớ).
maaartinus

Liên quan chặt chẽ: stackoverflow.com/questions/878309/
Ấn

Câu trả lời:


184

Không thấy câu trả lời đúng, mặc dù rất dễ kiểm tra.

Trong một máy ảo HotSpot gần đây, câu trả lời đúng là Integer.MAX_VALUE - 5. Một khi bạn đi xa hơn thế:

public class Foo {
  public static void main(String[] args) {
    Object[] array = new Object[Integer.MAX_VALUE - 4];
  }
}

Bạn lấy:

Exception in thread "main" java.lang.OutOfMemoryError:
  Requested array size exceeds VM limit

57
Tôi nghĩ rằng ý tưởng về downvote không có ý nghĩa trừ khi chúng ta sẵn sàng downvote câu trả lời rõ ràng và đơn giản là sai . Liệu sự khác biệt của năm byte thực sự có vấn đề trong thế giới thực, KHÔNG, tất nhiên là không. Nhưng điều đó làm tôi lo lắng rằng mọi người sẵn sàng đưa ra câu trả lời "có thẩm quyền" mà không cần thử xem nó có thực sự hiệu quả hay không. Đối với giới hạn bộ nhớ, tốt, DUH. Điều đó giống như nếu bạn hỏi tôi "bạn có thể ăn bao nhiêu nho?" và tôi nói "tốt, nó phụ thuộc vào số lượng tôi có trong tủ lạnh vào thời điểm đó."
Kevin Bourrillion

7
Bạn có biết tại sao nó sẽ không cung cấp cho bạn năm byte không? Đây có nhất thiết phải là một cái gì đó luôn xảy ra trong Java hay nó chỉ có thể liên quan đến bộ nhớ máy tính của bạn hay cái gì đó?
Taymon

17
@Kevin Bourrillion: Điều này dường như đã thay đổi, bằng cách sử dụng Oracle 1.7.0_07 tôi có thể phân bổ tối đa MAX_VALUE-2các yếu tố. Điều này độc lập với những gì tôi phân bổ và tôi thực sự tự hỏi VM có thể sử dụng hai "thứ" này để làm gì (độ dài không phù hợp với 2 byte).
maaartinus

3
@ TomášZato mới nhất tại Integer.MAX_VALUE+1, bạn sẽ có một số nguyên tràn. Kích thước mảng trong Java là int, không long; bất kể kiểu dữ liệu nào bạn lưu trữ trong mảng, byte hoặc tham chiếu của bạn. Chuỗi chỉ là tham chiếu đối tượng.
Có QUIT - Anony-Mousse

8
Số phần tử tối đa trong một mảng trong JDK 6 trở lên là Integer.MAX_VALUE - 2= 2 147 483 645. Java phân bổ thành công một mảng như vậy nếu bạn chạy nó với -Xmx13G. Nó thất bại với OutOfMemoryError: Java heap spacenếu bạn vượt qua -Xmx12G.
Alexey Ivanov

127

Điều này (tất nhiên) hoàn toàn phụ thuộc vào VM.

Duyệt qua các mã nguồn của OpenJDK 7 và 8 java.util.ArrayList, .Hashtable, .AbstractCollection, .PriorityQueue, và .Vector, bạn có thể thấy điều này khẳng định được lặp đi lặp lại:

/**
 * 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;

được Martin Buchholz (Google) thêm vào ngày 2010-05-09 ; được xem xét bởi Chris Hegarty (Oracle).

Vì vậy, có lẽ chúng ta có thể nói rằng số "an toàn" tối đa sẽ là 2 147 483 639 ( Integer.MAX_VALUE - 8) và "các nỗ lực phân bổ mảng lớn hơn có thể dẫn đến OutOfMemoryError ".

(Có, khiếu nại độc lập của Buchholz không bao gồm bằng chứng ủng hộ, vì vậy đây là một kháng cáo có tính toán đối với chính quyền. Ngay cả trong chính OpenJDK, chúng ta có thể thấy mã như return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;thể MAX_ARRAY_SIZEhiện chưa sử dụng thực sự .)


Và tại sao chúng ta cần thêm -8?
JohnWinter 13/07/2015

@Pacerier. Không nên áp dụng MAX_ARRAY_SIZE này khi bạn đang sử dụng ArrayList? Điều đó khác với việc sử dụng một mảng như int [] mảng = new int [some_value_here]; phải không Tại sao một hằng số được xác định trong ArrayList có thể được áp dụng cho một mảng bình thường (được định nghĩa bằng [])? Họ có giống nhau đằng sau hậu trường không?
Tiago

1
@Tiago, Không, bản thân mã không có gì để làm với kích thước tối đa của mảng. Đó chỉ là một yêu sách.
Pacerier

@JohnWinter, Câu trích dẫn nêu rõ "Một số VM dành một số từ tiêu đề trong một mảng". Vì vậy, đó -8là do các byte mà các từ tiêu đề dành riêng sẽ chiếm.
Pacerier

38

Thực tế có hai giới hạn. Một, phần tử tối đa có thể lập chỉ mục cho mảng và, hai, dung lượng bộ nhớ có sẵn cho ứng dụng của bạn. Tùy thuộc vào dung lượng bộ nhớ khả dụng và dung lượng được sử dụng bởi các cấu trúc dữ liệu khác, bạn có thể đạt giới hạn bộ nhớ trước khi bạn đạt đến phần tử mảng có thể định địa chỉ tối đa.


27

Tiếp theo bài viết này http://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays :

Java đã bị chỉ trích vì không hỗ trợ các mảng gồm hơn 2 31 1 (khoảng 2,1 tỷ) phần tử. Đây là một hạn chế của ngôn ngữ; Đặc tả ngôn ngữ Java, Phần 10.4, nói rằng:

Mảng phải được lập chỉ mục bởi các giá trị int ... Một nỗ lực truy cập vào một thành phần mảng có giá trị chỉ mục dài dẫn đến lỗi thời gian biên dịch.

Hỗ trợ các mảng lớn cũng sẽ yêu cầu thay đổi đối với JVM. Giới hạn này thể hiện ở các khu vực như bộ sưu tập bị giới hạn ở 2 tỷ phần tử và không có khả năng đối với các tệp bản đồ bộ nhớ lớn hơn 2 GiB. Java cũng thiếu các mảng đa chiều thực sự (các khối bộ nhớ đơn được phân bổ liên tục được truy cập bởi một chỉ định duy nhất), điều này hạn chế hiệu năng cho tính toán khoa học và kỹ thuật.


6
Java thiếu đường cú pháp cho các mảng nhiều chiều, nhưng bạn vẫn có thể "có" chúng với một chút nhân (trừ khi tổng kích thước của mảng vượt quá giới hạn đã nói ở trên)
kbolino 27/1/2016

11

Mảng là số nguyên không âm được lập chỉ mục, vì vậy kích thước mảng tối đa bạn có thể truy cập sẽ là Integer.MAX_VALUE. Điều khác là làm thế nào mảng lớn bạn có thể tạo ra. Nó phụ thuộc vào bộ nhớ tối đa có sẵn cho bạn JVMvà loại nội dung của mảng. Mỗi phần tử mảng có kích thước của nó, ví dụ. byte = 1 byte, int = 4 bytes,Object reference = 4 bytes (on a 32 bit system)

Vì vậy, nếu bạn có 1 MBbộ nhớ khả dụng trên máy, bạn có thể phân bổ một mảng byte[1024 * 1024]hoặc Object[256 * 1024].

Trả lời câu hỏi của bạn - Bạn có thể phân bổ một mảng kích thước (bộ nhớ / kích thước tối đa có sẵn của mục mảng).

Tóm tắt - Về mặt lý thuyết kích thước tối đa của một mảng sẽ là Integer.MAX_VALUE. Thực tế, nó phụ thuộc vào dung lượng bộ nhớ của bạn JVMvà bao nhiêu trong số đó đã được phân bổ cho các đối tượng khác.


3

Tôi đã cố gắng tạo một mảng byte như thế này

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

Với cấu hình chạy này:

-Xms4G -Xmx4G

Và phiên bản java:

Phiên bản Openjdk "1.8.0_141"

Môi trường thời gian chạy OpenJDK (bản dựng 1.8.0_141-b16)

OpenJDK 64-Bit Server VM (bản dựng 25.141-b16, chế độ hỗn hợp)

Nó chỉ hoạt động với x> = 2, có nghĩa là kích thước tối đa của một mảng là Integer.MAX_VALUE-2

Giá trị trên cho

Ngoại lệ trong luồng "chính" java.lang.OutOfMemoryError: Kích thước mảng được yêu cầu vượt quá giới hạn VM tại Main.main (Main.java:6)


2

Có, có giới hạn trên mảng java. Java sử dụng một số nguyên làm chỉ mục cho mảng và lưu trữ số nguyên tối đa của JVM là 2 ^ 32. vì vậy bạn có thể lưu trữ 2.147.483.647 phần tử trong mảng.

Trong trường hợp bạn cần nhiều hơn độ dài tối đa, bạn có thể sử dụng hai mảng khác nhau nhưng phương pháp được đề xuất là lưu trữ dữ liệu vào một tệp. bởi vì lưu trữ dữ liệu trong tệp không có giới hạn. bởi vì các tệp được lưu trữ trong trình điều khiển lưu trữ của bạn nhưng mảng được lưu trữ trong JVM. JVM cung cấp không gian hạn chế để thực hiện chương trình.


1

Số phần tử tối đa của một array(2^31)−1hoặc2 147 483 647


5
Java không thể phân bổ mảng kích thước Integer.MAX_VALUE - 1, bạn sẽ nhận được "java.lang.OutOfMemoryError: Kích thước mảng được yêu cầu vượt quá giới hạn VM". Số phần tử tối đa trong JDK 6 trở lên là Integer.MAX_VALUE - 2= 2 147 483 645.
Alexey Ivanov

0

Trên thực tế, giới hạn java của nó giới hạn ở mức 2 ^ 30-4 là 1073741820. Không phải 2 ^ 31-1. Dunno tại sao nhưng tôi đã thử nó bằng tay trên jdk. 2 ^ 30-3 vẫn ném vm trừ

Chỉnh sửa: đã sửa -1 thành -4, kiểm tra trên windows jvm


Bạn đang sử dụng JVM 32 bit. Sử dụng JVM 64 bit và giới hạn JVM sẽ gần bằng 2 ^ 31. (Bạn cũng cần không gian heap có sẵn, không phải là mặc định và sẽ bị ảnh hưởng bởi bộ nhớ vật lý của bạn.)
dave_thedom_085
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.