Java dizilerinin maksimum boyutu var mı?


214

Bir Java dizisinin içerebileceği öğe sayısında bir sınırlama var mı? Eğer öyleyse, nedir?


5
Yanlış bir yanıtı kabul ettiniz, sadece böyle uzun bir dizi ayırmayı deneyin (ve hayır, hafızam tükenmiyor).
maaartinus


Yanıtlar:


184

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

57
Bence iniş çıkışlar fikri, basit ve yanlış olan cevapları intikam etmek istemedikçe hiçbir anlam ifade etmiyor . Beş bayt arasındaki fark gerçek dünyada gerçekten önemli mi, HAYIR, elbette hayır. Ama beni ilgilendiren şey, gerçekten işe yarayıp yaramadığını görmek için bile denemeden "yetkili" olarak cevap vermeye istekli olmaları. Bellek sınırına gelince, DUH. Bana "kaç üzüm yiyebilirsin?" ve dedim ki "o zaman buzdolabında kaç tane bulunduğuma bağlı."
Kevin Bourrillion

7
Sana neden bu beş baytı vermeyeceğini biliyor musun ? Bu mutlaka Java'da her zaman olan bir şey midir, yoksa sadece bilgisayarınızın belleğiyle veya bir şeyle ilişkili olabilir mi?
Taymon

17
@Kevin Bourrillion: Bu değişmiş gibi görünüyor, Oracle 1.7.0_07 kullanarak MAX_VALUE-2Elemanlara 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).
maaartinus

3
@ TomášZato en son, Integer.MAX_VALUE+1bir tamsayı taşması olacak. Java'daki dizi boyutları intdeğil long; dizinizde, baytlarda veya referanslarda hangi veri türünü saklarsanız kullanın. Dizeler sadece Nesne referanslarıdır.
QUIT - Anony-Mousse

8
JDK 6 ve üzerindeki bir dizideki maksimum öğe sayısı 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 spaceEğer geçerseniz başarısız olur -Xmx12G.
Alexey Ivanov

127

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


Ve neden eklememiz gerekiyor -8?
JohnWinter

@Pacerier. Bu MAX_ARRAY_SIZE yalnızca ArrayList kullanırken uygulanmamalıdır mı? Bu, int [] array = new int [some_value_here]; gibi bir dizi kullanmaktan farklıdır; değil mi? ArrayList'te tanımlanan bir sabit neden normal bir diziye ([] ile tanımlanan) uygulanabilir? Sahne arkasında aynı mı?
Tiago

1
@Tiago, Hayır, kodun kendisinin dizilerin maksimum boyutu ile ilgisi yok. Bu sadece bir iddia.
Pacerier

@JohnWinter, Alıntıda "Bazı VM'ler bir dizide bazı başlık kelimeleri ayırır" yazıyor. Bu yüzden -8ayrılmış başlık kelimelerinin işgal edeceği bayttan kaynaklanmaktadır.
Pacerier

38

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.


27

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.


6
Java, çok boyutlu diziler için sözdizimsel şekerden yoksundur, ancak yine de bunlara biraz çarpma ile "sahip olabilirsiniz" (dizinin toplam boyutu yukarıda belirtilen sınırı aşmadığı sürece)
kbolino

11

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 JVMve 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 MBmakinenizde 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 JVMve bunun ne kadarının başka nesnelere tahsis edildiğine bağlıdır.


3

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


2

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.


1

Bir elemanlarının maksimum sayısı arrayolduğu (2^31)−1ya da2 147 483 647


5
Java boyut dizisini Integer.MAX_VALUE - 1ayı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.
Alexey Ivanov

0

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


32 bit JVM kullanıyorsunuz. 64 bit JVM kullanın ve JVM sınırı 2 ^ 31'e yakın olacaktır. (Ayrıca, varsayılan olmayan ve fiziksel belleğinizden etkilenecek olan yığın alanına da ihtiyacınız vardır.)
dave_thompson_085
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.