Trích dẫn tin nhắn Troubleshooting Guide for Java SE 6 with HotSpot VM
3.1.3 Chi tiết: Requested array size exceeds VM limit
(inline đậm là của tôi):
Chi tiết nhắn Requested array size exceeds VM limit
chỉ ra rằng ứng dụng (hoặc các API được sử dụng bởi ứng dụng đó) cố gắng phân bổ một mảng lớn hơn kích thước heap. Ví dụ: nếu ứng dụng cố gắng phân bổ một mảng 512MB nhưng kích thước heap tối đa là 256MB thì OutOfMemoryError
sẽ bị ném với lý do Requested array size exceeds VM limit
. Trong hầu hết các trường hợp, sự cố là vấn đề cấu hình (kích thước heap quá nhỏ) hoặc lỗi dẫn đến ứng dụng cố tạo một mảng lớn, ví dụ: khi số lượng phần tử trong mảng được tính bằng một thuật toán tính toán kích thước không chính xác.
UPDATE: khuyến khích bởi các @Pacerier tôi đã làm một số thử nghiệm nhanh chóng.Tôi đã viết một chương trình mẫu:
public class VmLimitTest {
public static final int SIZE = 2;
public static void main(String[] args) throws InterruptedException {
while(true) {
byte[] a = new byte[SIZE * 1024 * 1024];
TimeUnit.MILLISECONDS.sleep(10);
}
}
}
Và chạy nó với các tùy chọn JVM sau:
-Xms192m -Xmx192m -XX:NewRatio=2 -XX:SurvivorRatio=6 -XX:+PrintGCDetails
Đây là ý nghĩa của chúng:
- Cả đống là 192 MiB (
-Xms192m -Xmx192m
)
- Không gian thế hệ trẻ (eden + survivor) là 64 MiB, thế hệ cũ là 128 MiB (
-XX:NewRatio=2
)
- Mỗi không gian sống sót (trong số hai) là 8 MiB, vì vậy 48 MiB còn lại cho eden (1: 6 tỷ lệ,
-XX:SurvivorRatio=6
)
Trong khi kiểm tra tôi phát hiện ra những điều sau đây:
- Nếu mảng mới được tạo có thể vừa với eden (dưới 48 MiB), chương trình chạy tốt
- Đáng ngạc nhiên, khi kích thước mảng vượt quá kích thước eden, nhưng có thể vừa với eden và không gian sống sót (từ 48 đến 56 MiB), JVM có thể phân bổ một đối tượng duy nhất trên cả eden và survivor (chồng chéo tw o khu vực). Khéo léo!
- Khi kích thước mảng vượt quá eden + đơn sống sót (trên 56 MiB) đối tượng mới được tạo sẽ được đặt trực tiếp trong thế hệ cũ, bỏ qua không gian eden và người sống sót. Điều này cũng có nghĩa là đột ngột GC đầy đủ được thực hiện tất cả các thời gian - rất xấu!
- tôi có thể dễ dàng phân bổ 127 MiB dữ liệu nhưng cố gắng để phân bổ 129 MiB sẽ ném
OutOfMemoryError: Java heap space
Đây là điểm mấu chốt - bạn không thể tạo một đối tượng với kích thước lớn hơn so với thế hệ cũ. Cố gắng làm như vậy sẽ dẫn đến lỗi OutOfMemoryError: Java heap space
. Vì vậy, khi chúng ta có thể mong đợi đáng sợ Requested array size exceeds VM limit
?
Tôi đã thử chạy cùng một chương trình với nhiều đối tượng lớn hơn. Nhấn vào giới hạn độ dài mảng tôi chuyển sang long[]
và có thể dễ dàng lên tới 7 GiB. Với 128 MiB của heap tối đa khai báo JVM vẫn đang ném OutOfMemoryError: Java heap space
(!) Tôi đã quản lý để kích hoạt lỗi OutOfMemoryError: Requested array size exceeds VM limit
cố gắng phân bổ 8 GiB trong một đối tượng duy nhất. Tôi đã thử nghiệm điều này trên một máy tính Linux 32 bit với 3 GiB bộ nhớ vật lý và 1 GiB trao đổi.
Điều đó đang được nói rằng có thể bạn không bao giờ nên nhấn lỗi này. Các tài liệu có vẻ không chính xác/lỗi thời, nhưng nó là đúng trong một kết luận: điều này có lẽ là một lỗi vì việc tạo các mảng lớn như vậy là rất không phổ biến.
Nguồn
2012-01-29 12:38:28
Xem http://stackoverflow.com/questions/1880687/how-to-simulate-the-out-of-memory-requested-array-size-exceeds-vm-limit – skaffman