Есть ли ограничение на количество элементов, которые может содержать массив 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
элементов. Это не зависит от того, что я выделяю, и мне действительно интересно, для чего виртуальная машина может использовать две «вещи» (длина не помещается в 2 байта).
Integer.MAX_VALUE+1
вас будет целочисленное переполнение. Размеры массива в Java есть int
, нет long
; независимо от того, какой тип данных вы храните в своем массиве, байтах или ссылках. Строки - это просто ссылки на объекты.
Integer.MAX_VALUE - 2
= 2 147 483 645. Java успешно выделяет такой массив, если вы запускаете его с -Xmx13G
. Это не с, OutOfMemoryError: Java heap space
если вы пройдете -Xmx12G
.
Это (конечно) полностью 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;
который добавлен Мартином Бухгольцем (Google) 2010-05-09 ; проверено Крисом Хегарти (Oracle).
Таким образом, вероятно, мы можем сказать, что максимальное «безопасное» число будет 2 147 483 639 ( Integer.MAX_VALUE - 8
), а «попытки выделить большие массивы могут привести к OutOfMemoryError ».
(Да, отдельная претензия Бухгольца не включает подтверждающих доказательств, так что это расчетное обращение к авторитету. Даже в самом 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 миллиарда) элементов. Это ограничение языка; Спецификация языка Java, раздел 10.4, гласит, что:
Массивы должны быть проиндексированы значениями int ... Попытка доступа к компоненту массива с длинным значением индекса приводит к ошибке времени компиляции.
Поддержка больших массивов также потребует изменений в JVM. Это ограничение проявляется в таких областях, как количество коллекций, ограниченное 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-битная серверная виртуальная машина OpenJDK (сборка 25.141-b16, смешанный режим)
Это работает только для x> = 2, что означает, что максимальный размер массива равен Integer.MAX_VALUE-2
Значения выше этого дают
Исключение в потоке "main" java.lang.OutOfMemoryError: Размер запрашиваемого массива превышает ограничение виртуальной машины в Main.main (Main.java:6)
Да, есть ограничение на массив Java. Java использует целое число в качестве индекса массива, а максимальное целочисленное хранилище JVM составляет 2 ^ 32. так что вы можете хранить 2 147 483 647 элементов в массиве.
Если вам нужно больше, чем max-length, вы можете использовать два разных массива, но рекомендуемый метод - сохранить данные в файл. потому что хранение данных в файле не имеет ограничений. потому что файлы хранятся в ваших драйверах хранения, но массив хранятся в JVM. JVM предоставляет ограниченное пространство для выполнения программы.
Максимальное количество элементов array
is (2^31)−1
или2 147 483 647
Integer.MAX_VALUE - 1
, вы получите «java.lang.OutOfMemoryError: Запрошенный размер массива превышает ограничение виртуальной машины». Максимальное количество элементов в JDK 6 и выше Integer.MAX_VALUE - 2
= 2 147 483 645.
На самом деле это ограничение Java, ограничивающее 2 ^ 30-4 1073741820. Не 2 ^ 31-1. Не знаю почему, но я проверил это вручную на JDK.2 ^ 30-3 до сих пор бросает вм, кроме
Редактировать: исправлено от -1 до -4, проверено на windows jvm