Чи існує обмеження кількості елементів, який може містити масив Java? Якщо так, то що це?
Чи існує обмеження кількості елементів, який може містити масив Java? Якщо так, то що це?
Відповіді:
Я не бачив правильної відповіді, хоча це дуже легко перевірити.
У недавньому 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
MAX_VALUE-2
елементів. Це не залежить від того, що я виділяю, і мені дуже цікаво, для чого VM може використовувати два "речі" (довжина не вміщується в 2 байти).
Integer.MAX_VALUE+1
вас буде ціле переповнення. Розміри масивів у Java - це int
, ні long
; незалежно від того, який тип даних ви зберігаєте у своєму масиві, байтах чи посиланнях. Рядки - це лише посилання на об'єкт.
Integer.MAX_VALUE - 2
= 2 147 483 645. Java успішно виділяє такий масив, якщо ви запускаєте його -Xmx13G
. Це не вдається, OutOfMemoryError: Java heap space
якщо ви проїдете -Xmx12G
.
Це, звичайно, повністю від ВМ.
Переглядаючи вихідний код 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;
який додав Мартін Буххолц (Google) 2010-05-09 ; переглянув Кріс Хегарті (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
?
-8
це пов'язано з байтами, зайняті зарезервованими словами заголовка.
Насправді є два межі. Один, максимальний елемент, який може індексуватися для масиву, і, два, об'єм пам'яті, доступної вашій програмі. Залежно від обсягу доступної пам’яті та обсягу, який використовується іншими структурами даних, ви можете досягти межі пам’яті, перш ніж досягти максимального адресованого елемента масиву.
Переходимо до цієї статті http://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays :
Java піддавали критиці за те, що вона не підтримує масиви більш ніж 2 31 −1 (приблизно 2,1 мільярда) елементів. Це обмеження мови; У розділі 10.4 специфікації мови Java зазначено, що:
Масиви повинні бути індексовані значеннями int ... Спроба отримати доступ до компонента масиву з великим значенням індексу призводить до помилки часу компіляції.
Підтримка великих масивів також вимагає змін до СВМ. Це обмеження проявляється в таких областях, як колекція, обмежена 2 мільярдами елементів та неможливість зберігання файлів карт пам'яті, більших за 2 Гб. Java також не вистачає справжніх багатовимірних масивів (безперервно виділяються одиничні блоки пам'яті, до яких звертається один індикатор), що обмежує продуктивність для науково-технічних обчислень.
Масиви індексуються невід'ємним цілим числом, тому максимальний розмір масиву, до якого ви можете отримати доступ, був би 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
є і яка частина вже розподілена на інші об’єкти.
Я намагався створити такий байтовий масив
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)
64-бітний VM сервера OpenJDK (збірка 25.141-b16, змішаний режим)
Він працює лише для x> = 2, що означає максимальний розмір масиву Integer.MAX_VALUE-2
Значення вище цього дають
Виняток у потоці "main" java.lang.OutOfMemoryError: Запитаний розмір масиву перевищує обмеження VM на Main.main (Main.java:6)
Так, у масиві java існує обмеження. Java використовує ціле число в якості індексу для масиву, а максимальне ціле число для JVM - 2 ^ 32. тож ви можете зберігати 2147 483 647 елементів у масиві.
Якщо вам потрібна більше максимальної довжини, ви можете використовувати два різних масиви, але рекомендований метод - це збереження даних у файл. тому що для зберігання даних у файлі немає обмежень. оскільки файли, що зберігаються у ваших драйверах пам’яті, але масив, зберігаються в JVM. JVM надає обмежений простір для виконання програми.
Максимальна кількість елементів array
є (2^31)−1
або2 147 483 647
Integer.MAX_VALUE - 1
, ви отримаєте "java.lang.OutOfMemoryError: Запитаний розмір масиву перевищує обмеження VM". Максимальна кількість елементів у JDK 6 і вище становить Integer.MAX_VALUE - 2
= 2 147 483 645.
Насправді це обмеження Java, обмежуючи його в 2 ^ 30-4, будучи 1073741820. Не 2 ^ 31-1. Не знаю чому, але я перевірив це вручну на jdk. 2 ^ 30-3 все ще кидає vm, за винятком
Редагувати: фіксовано від -1 до -4, встановлено прапорець у вікні jvm