Czy istnieje ograniczenie liczby elementów, które może zawierać tablica Java? Jeśli tak, co to jest?
Czy istnieje ograniczenie liczby elementów, które może zawierać tablica Java? Jeśli tak, co to jest?
Odpowiedzi:
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
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).
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.
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.
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).
-8?
-8to spowodowane bajtów zarezerwowanych header słowa zajmie.
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.
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.
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.
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)
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.
Maksymalna liczba elementów arrayto (2^31)−1lub2 147 483 647
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.
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