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ì?
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ì?
Câu trả lời:
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
MAX_VALUE-2
cá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).
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.
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 space
nếu bạn vượt qua -Xmx12G
.
Đ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_SIZE
hiện chưa sử dụng thực sự .)
-8
?
-8
là do các byte mà các từ tiêu đề dành riêng sẽ chiếm.
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.
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.
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 JVM
và 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 MB
bộ 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 JVM
và bao nhiêu trong số đó đã được phân bổ cho các đối tượng khác.
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)
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.
Số phần tử tối đa của một array
là (2^31)−1
hoặc2 147 483 647
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.
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