Bir Java dizisinin içerebileceği öğe sayısında bir sınırlama var mı? Eğer öyleyse, nedir?
Bir Java dizisinin içerebileceği öğe sayısında bir sınırlama var mı? Eğer öyleyse, nedir?
Yanıtlar:
Test edilmesi çok kolay olmasına rağmen doğru cevabı görmedim.
Son zamanlarda yapılan bir HotSpot VM'sinde doğru cevap Integer.MAX_VALUE - 5
. Bir kez bunun ötesine geçtiğinizde:
public class Foo {
public static void main(String[] args) {
Object[] array = new Object[Integer.MAX_VALUE - 4];
}
}
Şunları elde edersiniz:
Exception in thread "main" java.lang.OutOfMemoryError:
Requested array size exceeds VM limit
MAX_VALUE-2
Elemanlara kadar tahsis edebilirim . Bu, ayırdığım şeyden bağımsız ve VM'nin iki "şeyi" ne için kullanabileceğini merak ediyorum (uzunluk 2 bayta sığmıyor).
Integer.MAX_VALUE+1
bir tamsayı taşması olacak. Java'daki dizi boyutları int
değil long
; dizinizde, baytlarda veya referanslarda hangi veri türünü saklarsanız kullanın. Dizeler sadece Nesne referanslarıdır.
Integer.MAX_VALUE - 2
= 2 147 483 645'tir. Java, böyle bir diziyi çalıştırırsanız başarıyla ayırır -Xmx13G
. OutOfMemoryError: Java heap space
Eğer geçerseniz başarısız olur -Xmx12G
.
Bu (elbette) tamamen VM'ye bağımlıdır.
OpenJDK 7 ve 8 kaynak koduna göz tarama java.util.ArrayList
, .Hashtable
, .AbstractCollection
, .PriorityQueue
, ve .Vector
, bunu görebilirsiniz iddia tekrarlanıyor:
/** * 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;
2010-05-09 tarihinde Martin Buchholz (Google) tarafından eklenen ; Chris Hegarty (Oracle) tarafından gözden geçirilmiştir.
Yani, muhtemelen maksimum "güvenli" sayının 2 147 483 639 ( Integer.MAX_VALUE - 8
) olacağını söyleyebiliriz ve "daha büyük dizileri ayırma girişimleri OutOfMemoryError ile sonuçlanabilir ".
(Evet, Buchholz'un bağımsız iddiası destekleyici kanıt içermiyor, bu yüzden bu otoriteye hesaplanmış bir çekicilik. OpenJDK'da bile, henüz gerçek bir kullanım olmadığını return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
gösteren kodu görebiliriz .)MAX_ARRAY_SIZE
-8
?
-8
ayrılmış başlık kelimelerinin işgal edeceği bayttan kaynaklanmaktadır.
Aslında iki sınır vardır. Birincisi, dizi için dizine eklenebilir maksimum öğe ve ikincisi uygulamanız için kullanılabilir bellek miktarı. Kullanılabilir bellek miktarına ve diğer veri yapıları tarafından kullanılan miktara bağlı olarak, adreslenebilir maksimum dizi öğesine ulaşmadan önce bellek sınırına vurabilirsiniz.
Bu makaleye göre http://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays :
Java, 2 31 −1'den (yaklaşık 2,1 milyar) fazla diziyi desteklemediği için eleştirildi . Bu dilin bir sınırlamasıdır; Java Dil Belirtimi, Bölüm 10.4, şunları belirtir:
Diziler int değerleri ile dizine eklenmelidir ... Uzun bir dizin değerine sahip bir dizi bileşenine erişim denemesi derleme zamanı hatasına neden olur.
Büyük dizileri desteklemek için JVM'de de değişiklik yapılması gerekir. Bu sınırlama, koleksiyonların 2 milyar elemanla sınırlı olması ve 2 GiB'den büyük harita dosyalarının hafızaya alınamaması gibi alanlarda kendini gösterir. Java ayrıca bilimsel ve teknik bilgi işlem için performansı sınırlayan gerçek çok boyutlu dizilerden (tek bir dolaylı erişimle bitişik olarak ayrılan tek bellek blokları) yoksundur.
Diziler negatif olmayan bir tamsayı dizine eklenir, bu nedenle erişebileceğiniz maksimum dizi boyutu olur Integer.MAX_VALUE
. Diğer şey, ne kadar büyük bir dizi oluşturabileceğinizdir. Kullanabileceğiniz maksimum belleğe JVM
ve dizinin içerik türüne bağlıdır. Her dizi öğesinin boyutu vardır, örnek. byte = 1 byte
, int = 4 bytes
,Object reference = 4 bytes (on a 32 bit system)
Dolayısıyla 1 MB
makinenizde kullanılabilir bellek varsa , byte[1024 * 1024]
veya dizisi ayırabilirsiniz Object[256 * 1024]
.
Sorunuzu cevaplama - Bir dizi boyut ayırabilirsiniz (kullanılabilir maksimum bellek / dizi öğesinin boyutu).
Özet - Teorik olarak bir dizinin maksimum boyutu olacaktır Integer.MAX_VALUE
. Pratik olarak, ne kadar belleğiniz olduğuna JVM
ve bunun ne kadarının başka nesnelere tahsis edildiğine bağlıdır.
Böyle bir bayt dizisi oluşturmaya çalıştım
byte[] bytes = new byte[Integer.MAX_VALUE-x];
System.out.println(bytes.length);
Bu çalıştırma yapılandırmasıyla:
-Xms4G -Xmx4G
Ve java sürümü:
Openjdk sürümü "1.8.0_141"
OpenJDK Çalışma Zamanı Ortamı (derleme 1.8.0_141-b16)
OpenJDK 64 Bit Sunucu VM (yapı 25.141-b16, karışık mod)
Yalnızca x> = 2 için çalışır, yani bir dizinin maksimum boyutu Tamsayıdır.MAX_VALUE-2
Yukarıdaki değerler
"Main" dizisindeki istisna java.lang.OutOfMemoryError: İstenen dizi boyutu Main.main (Main.java:6) üzerindeki VM sınırını aşıyor
Evet, Java dizisinde sınır var. Java, diziye dizin olarak bir tamsayı kullanır ve JVM tarafından maksimum tamsayı deposu 2 ^ 32'dir. böylece dizide 2.147.483.647 eleman saklayabilirsiniz.
Maksimum uzunluktan daha fazlasına ihtiyacınız varsa, iki farklı dizi kullanabilirsiniz, ancak önerilen yöntem verileri bir dosyaya depolamaktır. çünkü veriyi dosyada saklamanın bir sınırı yoktur. çünkü depolama sürücülerinizde ancak dizide saklanan dosyalar JVM'de depolanır. JVM, programın yürütülmesi için sınırlı alan sağlar.
Bir elemanlarının maksimum sayısı array
olduğu (2^31)−1
ya da2 147 483 647
Integer.MAX_VALUE - 1
ayıramıyorsa, "java.lang.OutOfMemoryError: İstenen dizi boyutu VM sınırını aşıyor" iletisini alacaksınız. JDK 6 ve üstü için maksimum öğe sayısı Integer.MAX_VALUE - 2
= 2 147483 645'tir.
Aslında 2 ^ 30-4 ile java sınırlaması 1073741820 olmak. 2 ^ 31-1 değil. Neden bilmiyorum ama jdk üzerinde elle test. 2 ^ 30-3 hala vm atıyor
Düzenleme: sabit -1 ila -4, windows jvm üzerinde kontrol