Czy tablice Java mają maksymalny rozmiar?

214

Czy istnieje ograniczenie liczby elementów, które może zawierać tablica Java? Jeśli tak, co to jest?

Jaszczurka
źródło
5
Przyjąłeś złą odpowiedź, po prostu spróbuj przydzielić tak długą tablicę (i nie, nie brakuje mi pamięci).
maaartinus
Ściśle powiązane: stackoverflow.com/questions/878309/...
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Prawidłowa odpowiedź to stackoverflow.com/questions/31382531/...
Ivan Mamontov

Odpowiedzi:

184

Nie widziałem właściwej odpowiedzi, mimo że bardzo łatwo ją przetestować.

W najnowszej maszynie wirtualnej HotSpot poprawna odpowiedź to Integer.MAX_VALUE - 5. Po przekroczeniu tego:

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

Dostajesz:

Exception in thread "main" java.lang.OutOfMemoryError:
  Requested array size exceeds VM limit
Kevin Bourrillion
źródło
57
Myślę, że idea głosów negatywnych nie ma sensu, chyba że jesteśmy skłonni głosować negatywnie na odpowiedzi, które są jasne i po prostu błędne . Czy różnica pięciu bajtów w rzeczywistości ma znaczenie, NIE, oczywiście, że nie. Ale martwi mnie, że ludzie są gotowi udzielić odpowiedzi „autorytatywnie”, nawet nie próbując sprawdzić, czy to naprawdę działa. Jeśli chodzi o limit pamięci, cóż, DUH. To tak, jakbyś zapytał mnie „ile winogron można zjeść?” i powiedziałem „cóż, zależy to od tego, ile mam w lodówce w danym momencie”.
Kevin Bourrillion
7
Czy wiesz, dlaczego nie da ci tych pięciu bajtów? Czy to koniecznie dzieje się zawsze w Javie, czy może to być związane z pamięcią komputera lub czymś takim?
Taymon
17
@Kevin Bourrillion: Wygląda na to, że się zmieniło, używając Oracle 1.7.0_07 mogę przydzielić do MAX_VALUE-2elementów. Jest to niezależne od tego, co przydzielam i naprawdę zastanawiam się, do czego maszyna wirtualna może użyć dwóch „rzeczy” (długość nie mieści się w 2 bajtach).
maaartinus
3
@ TomášZato najpóźniej o Integer.MAX_VALUE+1, nastąpi przepełnienie liczb całkowitych. Rozmiary tablic w Javie intnie są long; bez względu na typ danych przechowywanych w tablicy, bajtach lub referencjach. Ciągi to tylko odwołania do obiektów.
Ma ZAKOŃCZENIE - Anony-Mousse
8
Maksymalna liczba elementów w tablicy w JDK 6 i wyższych wynosi Integer.MAX_VALUE - 2= 2 147 483 645. Java pomyślnie alokuje taką tablicę, jeśli ją uruchomisz -Xmx13G. Nie powiedzie się, OutOfMemoryError: Java heap spacejeśli zdasz -Xmx12G.
Aleksiej Iwanow
127

Jest to (oczywiście) całkowicie zależne od VM.

Przeglądanie kodu źródłowego OpenJDK 7 i 8 java.util.ArrayList, .Hashtable, .AbstractCollection, .PriorityQueue, i .Vectormożna zobaczyć, to twierdzenie powtarzane:

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

który dodaje Martin Buchholz (Google) w dniu 09.05.2010 ; recenzowane przez Chris Hegarty (Oracle).

Więc chyba można powiedzieć, że maksymalna „bezpieczne” liczba będzie 2 147 483 639 ( Integer.MAX_VALUE - 8) i „próby przeznaczyć większe tablice mogą spowodować OutOfMemoryError ”.

(Tak, samodzielne roszczenie Buchholza nie obejmuje dowodów potwierdzających, więc jest to obliczone odwołanie do organu. Nawet w samym OpenJDK możemy zobaczyć kod, return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;który pokazuje, że MAX_ARRAY_SIZEnie ma jeszcze rzeczywistego zastosowania).

Pacerier
źródło
I dlaczego musimy dodać -8?
JohnWinter,
@Pacerier. Czy ten MAX_ARRAY_SIZE nie powinien być stosowany tylko wtedy, gdy używasz ArrayList? Różni się to od używania tablicy takiej jak int [] array = new int [some_value_here]; prawda? Dlaczego stałą zdefiniowaną w ArrayList można zastosować do normalnej tablicy (zdefiniowanej za pomocą [])? Czy są takie same za kulisami?
Tiago,
1
@Tiago, nie, sam kod nie ma nic wspólnego z maksymalnym rozmiarem tablic. To tylko roszczenie.
Pacerier
@JohnWinter, cytat stwierdza „Niektóre maszyny wirtualne rezerwują niektóre słowa nagłówkowe w tablicy”. Więc -8to spowodowane bajtów zarezerwowanych header słowa zajmie.
Pacerier
38

W rzeczywistości istnieją dwa ograniczenia. Po pierwsze, maksymalny element indeksowalny dla tablicy, a po drugie ilość pamięci dostępnej dla twojej aplikacji. W zależności od ilości dostępnej pamięci i ilości wykorzystywanej przez inne struktury danych, możesz przekroczyć limit pamięci, zanim osiągniesz maksymalny adresowalny element tablicy.

tvanfosson
źródło
27

Przechodząc do tego artykułu http://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays :

Java krytykowane przez nie podtrzymuje tablicę więcej niż 2 31 -1 (około 2100000000) elementów. To jest ograniczenie języka; specyfikacja języka Java, sekcja 10.4, stwierdza, że:

Tablice muszą być indeksowane według wartości int ... Próba uzyskania dostępu do komponentu tablicy o długiej wartości indeksu powoduje błąd czasu kompilacji.

Obsługa dużych tablic wymagałaby również zmian w JVM. Ograniczenie to przejawia się w obszarach takich jak zbiory ograniczone do 2 miliardów elementów i niemożność zapisania plików map pamięci większych niż 2 GiB. Java nie ma również prawdziwych wielowymiarowych tablic (przylegających do siebie pojedynczych bloków pamięci, do których dostęp uzyskuje jedna pośrednia), co ogranicza wydajność obliczeń naukowych i technicznych.

pracujący
źródło
6
Java nie ma cukru syntaktycznego dla tablic wielowymiarowych, ale nadal można je „mieć” z odrobiną mnożenia (chyba że całkowity rozmiar tablicy przekroczył wspomniany limit)
kbolino
11

Tablice są nieujemnymi indeksowanymi liczbami całkowitymi, więc maksymalny rozmiar tablicy, do której można uzyskać dostęp, wynosiłby Integer.MAX_VALUE. Drugą rzeczą jest to, jak dużą tablicę możesz stworzyć. Zależy to od maksymalnej dostępnej pamięci JVMi typu zawartości tablicy. Każdy element tablicy ma swój rozmiar, przykład. byte = 1 byte, int = 4 bytes,Object reference = 4 bytes (on a 32 bit system)

Więc jeśli masz 1 MBpamięć na swoim komputerze, możesz przydzielić tablicę byte[1024 * 1024]lub Object[256 * 1024].

Odpowiadając na pytanie - Możesz przydzielić tablicę rozmiaru (maksymalna dostępna pamięć / rozmiar elementu tablicy).

Podsumowanie - Teoretycznie maksymalny rozmiar tablicy będzie Integer.MAX_VALUE. Praktycznie zależy to od tego, ile pamięci masz JVMi ile już zostało przydzielone innym obiektom.

Dhanuka
źródło
3

Próbowałem utworzyć tablicę bajtów w ten sposób

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

Dzięki tej konfiguracji uruchamiania:

-Xms4G -Xmx4G

I wersja Java:

Wersja Openjdk „1.8.0_141”

Środowisko wykonawcze OpenJDK (kompilacja 1.8.0_141-b16)

64-bitowa maszyna wirtualna serwera OpenJDK (kompilacja 25.141-b16, tryb mieszany)

Działa tylko dla x> = 2, co oznacza, że ​​maksymalny rozmiar tablicy to Integer.MAX_VALUE-2

Wartości powyżej tego dają

Wyjątek w wątku „main” java.lang.OutOfMemoryError: Żądany rozmiar tablicy przekracza limit VM na Main.main (Main.java:6)

Vasilis Nicolaou
źródło
2

Tak, istnieje limit dla tablicy Java. Java używa liczby całkowitej jako indeksu tablicy, a maksymalna liczba przechowywanych liczb całkowitych wg JVM wynosi 2 ^ 32. dzięki czemu można przechowywać w tablicy 2 147 483 647 elementów.

Jeśli potrzebujesz więcej niż maksymalnej długości, możesz użyć dwóch różnych tablic, ale zalecaną metodą jest przechowywanie danych w pliku. ponieważ przechowywanie danych w pliku nie ma ograniczeń. ponieważ pliki przechowywane w sterownikach pamięci, ale macierze są przechowywane w JVM. JVM zapewnia ograniczoną przestrzeń do wykonywania programu.

Avinash Barde
źródło
1

Maksymalna liczba elementów arrayto (2^31)−1lub2 147 483 647

Niemowlę
źródło
5
Java nie może przydzielić tablicy rozmiaru Integer.MAX_VALUE - 1, otrzymasz „java.lang.OutOfMemoryError: Żądany rozmiar tablicy przekracza limit VM”. Maksymalna liczba elementów w JDK 6 i wyższych wynosi Integer.MAX_VALUE - 2= 2 147 483 645.
Aleksiej Iwanow
0

W rzeczywistości jest to ograniczenie Java, które ma wartość 2 ^ 30-4, czyli 1073741820. Nie 2 ^ 31-1. Nie wiem dlaczego, ale przetestowałem to ręcznie na jdk. 2 ^ 30-3 wciąż rzuca vm oprócz

Edycja: naprawiono od -1 do -4, zaznaczone w Windows Jvm

Paproć
źródło
Używasz 32-bitowej maszyny JVM. Użyj 64-bitowej maszyny JVM, a limit maszyny JVM będzie bliski 2 ^ 31. (Potrzebujesz również dostępnego miejsca na stercie, co nie jest domyślne i na które wpłynie twoja pamięć fizyczna.)
dave_thompson_085 10.09