Linux altında Java'dan Sanal Bellek Kullanımı, çok fazla bellek kullanılmış


259

Linux altında çalışan bir Java uygulaması ile ilgili bir sorunum var.

Uygulamayı başlattığımda, varsayılan maksimum yığın boyutunu (64 MB) kullanarak, 240 MB sanal Belleğin uygulamaya tahsis edildiğini tops uygulamasını görüyorum. Bu, bilgisayardaki nispeten kaynak sınırlı olan diğer bazı yazılımlarla bazı sorunlar yaratır.

Ayrılmış sanal bellek zaten anladığım kadarıyla kullanılmayacak, çünkü yığın sınırına ulaştığımızda bir OutOfMemoryErrora atıyor. Aynı uygulamayı pencereler altında çalıştırdım ve Sanal Bellek boyutu ile Yığın boyutunun benzer olduğunu görüyorum.

Yine de Linux altında bir Java işlemi için kullanılan Sanal Belleği yapılandırabilir miyim?

Düzenleme 1 : Sorun Yığın değil. Sorun, örneğin 128 MB'lık bir Yığın ayarlarsam, hala Linux'un 210 MB Sanal Bellek ayırmasıdır, bu da hiç gerekli değildir. **

Edit 2 : Kullanmak ulimit -vsanal bellek miktarını sınırlamaya izin verir. Ayarlanan boyut 204 MB'ın altındaysa, 204 MB'ye, ancak 64 MB'ye ihtiyaç duymasa bile uygulama çalışmaz. Java'nın neden bu kadar çok sanal bellek gerektirdiğini anlamak istiyorum. Bu değiştirilebilir mi?

Edit 3 : Sistemde çalışan ve gömülü olan birkaç uygulama daha vardır. Ve sistemin sanal bir bellek limiti var (yorumlar, önemli ayrıntılar).


Neden sanal bellek kullanımı ile ilgileniyorsunuz? Gerçekten endişelenmek istiyorsanız, yerleşik bellek kullanımına bakın ve şu komutları okuyun: free, ps, top.
basszero

2
Sistemde çalışan, gömülü olan birkaç uygulama daha vardır. Ve sistemin sanal bellek limiti var.
Mario Ortegon

ahhhh, şeytan ayrıntılarda
basszero

Hangi Java uygulamasını kullanıyorsunuz? Bataklık standardı (OpenJDK olmayan) ücretsiz Sun JRE, IIRC'nin gömülü kullanım için lisanslanmamıştır.
Tom Hawtin - tackline

Ben "gömülü" kısmı özledim düşünüyorum ... bellek sınırlı ve donanım özelleştirilmiş, ama yine de standart bir bilgisayar
Mario Ortegón

Yanıtlar:


630

Bu, Java ile uzun süredir devam eden bir şikayetti, ancak büyük ölçüde anlamsız ve genellikle yanlış bilgilere bakmaya dayanıyor. Her zamanki ifade "Java'da Merhaba Dünya 10 megabayt alır! Neden buna ihtiyacı var?" 64 bit JVM'de Hello World'ü 4 gigabaytın üzerinde bir iddiada bulunmanın bir yolu var ... en azından bir ölçüm biçimiyle.

java -Xms1024m -Xmx4096m com.example.Hello

Belleği Ölçmenin Farklı Yolları

Linux'ta, üst komut size bellek için birkaç farklı sayı verir. Merhaba Dünya örneği hakkında şöyle diyor:

  PID KULLANICI PR NI VIRT RES SHR S% CPU% MEM ZAMANI + KOMUT
 2120 kilogramlık 20 0 4373m 15m 7152 S 0 0.2 0: 00.10 java
  • VIRT sanal bellek alanıdır: sanal bellek haritasındaki her şeyin toplamı (aşağıya bakınız). Olmadığı durumlar dışında büyük ölçüde anlamsızdır (aşağıya bakınız).
  • RES yerleşik ayarlanan boyuttur: RAM'de mevcut olan sayfa sayısı. Hemen hemen her durumda, "çok büyük" derken kullanmanız gereken tek sayı budur. Ancak özellikle Java hakkında konuşurken hala çok iyi bir sayı değil.
  • SHR, diğer işlemlerle paylaşılan yerleşik bellek miktarıdır. Java işlemi için bu genellikle paylaşılan kitaplıklar ve bellek eşlemeli JAR dosyaları ile sınırlıdır. Bu örnekte, yalnızca bir Java işlemi çalışıyordu, bu yüzden 7k'nin işletim sistemi tarafından kullanılan kitaplıklardan kaynaklandığından şüpheleniyorum.
  • SWAP varsayılan olarak açık değildir ve burada gösterilmez. Takas alanında olsun ya da olmasın, o anda diskte yerleşik olan sanal bellek miktarını gösterir . İşletim sistemi, aktif sayfaları RAM'de tutmak konusunda çok iyidir ve takas için tek tedavi (1) daha fazla bellek satın almak veya (2) işlem sayısını azaltmaktır, bu nedenle bu sayıyı göz ardı etmek en iyisidir.

Windows Görev Yöneticisi'nin durumu biraz daha karmaşıktır. Windows XP'de "Bellek Kullanımı" ve "Sanal Bellek Boyutu" sütunları vardır, ancak resmi belgeler ne anlama geldiklerine sessizdir. Windows Vista ve Windows 7 daha fazla sütun ekler ve bunlar aslında belgelenir . Bunlardan "Çalışma Seti" ölçümü en yararlı olanıdır; kabaca Linux'taki RES ve SHR toplamına karşılık gelir.

Sanal Bellek Haritasını Anlama

Bir işlem tarafından tüketilen sanal bellek, işlem belleği haritasında bulunan her şeyin toplamıdır. Buna veriler (ör. Java yığını), ancak program tarafından kullanılan tüm paylaşılan kitaplıklar ve bellek eşlemeli dosyalar da dahildir. Linux'ta, işlem alanına eşlenen tüm şeyleri görmek için pmap komutunu kullanabilirsiniz (buradan sonra sadece Linux'a başvuracağım çünkü kullandığım şey bu; Pencereler). İşte "Merhaba Dünya" programının hafıza haritasından bir alıntı; tüm hafıza haritası 100 satırdan daha uzun ve bin satırlı bir listeye sahip olmak olağandışı değil.

0000000040000000 36K rx-- /usr/local/java/jdk-1.6-x64/bin/java
0000000040108000 8K rwx-- /usr/local/java/jdk-1.6-x64/bin/java
0000000040eba000 676K rwx - [anon]
00000006fae00000 21248K rwx - [anon]
00000006fc2c0000 62720K rwx - [anon]
0000000700000000 699072K rwx - [anon]
000000072aab0000 2097152K rwx - [anon]
00000007aaab0000 349504K rwx - [anon]
00000007c0000000 1048576K rwx - [anon]
...
00007fa1ed00d000 1652K r-xs- /usr/local/java/jdk-1.6-x64/jre/lib/rt.jar
...
00007fa1ed1d3000 1024K rwx - [anon]
00007fa1ed2d3000 4K ----- [anon]
00007fa1ed2d4000 1024K rwx - [anon]
00007fa1ed3d4000 4K ----- [anon]
...
00007fa1f20d3000 164K rx-- /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
00007fa1f20fc000 1020K ----- /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
00007fa1f21fb000 28K rwx-- /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
...
00007fa1f34aa000 1576K rx-- /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3634000 2044K ----- /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3833000 16K rx-- /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3837000 4K rwx-- /lib/x86_64-linux-gnu/libc-2.13.so
...

Biçimin hızlı bir açıklaması: her satır, segmentin sanal bellek adresiyle başlar. Bunu segment boyutu, izinler ve segmentin kaynağı izler. Bu son öğe, mmap yoluyla ayrılan bir bellek bloğunu gösteren bir dosya veya "anon" dur .

Yukarıdan başlayarak,

  • JVM yükleyici (yani, yazarken çalıştırılan program java). Bu çok küçük; tüm yaptığı gerçek JVM kodunun saklandığı paylaşılan kütüphanelere yüklenmektir.
  • Java yığınını ve dahili verileri tutan bir grup anon bloğu. Bu bir Sun JVM'dir, bu nedenle yığın, her biri kendi bellek bloğu olan birden fazla nesle bölünür. JVM'nin -Xmxdeğere bağlı olarak sanal bellek alanı ayırdığını unutmayın ; bu onun bitişik bir yığın olmasını sağlar. -XmsDeğeri programı başlar ve tetik çöp toplama için bu sınır yaklaşılırken zaman "kullanımda" ne kadar yığın söylemek dahili olarak kullanılır.
  • Bellek eşlemeli JARfile, bu durumda "JDK sınıflarını" tutan dosya. Bir JAR'ı bellek eşlediğinizde, içindeki dosyalara çok verimli bir şekilde erişebilirsiniz (her seferinde başlangıçtan okumak yerine). Sun JVM, sınıf yolundaki tüm JAR'ları bellekle eşler; uygulama kodunuzun bir JAR'a erişmesi gerekiyorsa, bunu bellek eşlemesiyle de eşleştirebilirsiniz.
  • İki iş parçacığı için iş parçacığı başına veri. 1M bloğu iplik yığınıdır. 4k bloğu için iyi bir açıklamam yoktu, ancak @ericsoe bunu bir "koruma bloğu" olarak tanımladı: okuma / yazma izinleri yok, bu yüzden erişilirse bir segment hatasına neden olur ve JVM bunu yakalar ve çevirir a StackOverFlowError. Gerçek bir uygulama için, bu girişlerin yüzlerce değilse bellek haritasında tekrar tekrar onlarca göreceksiniz.
  • Gerçek JVM kodunu barındıran paylaşılan kitaplıklardan biri. Bunlardan birkaç tane var.
  • C standart kitaplığı için paylaşılan kitaplık. Bu, JVM'nin kesinlikle Java'nın bir parçası olmayan yüklerinden sadece bir tanesidir.

Paylaşılan kitaplıklar özellikle ilginçtir: her paylaşılan kitaplık en az iki bölümden oluşur: kitaplık kodunu içeren salt okunur bir segment ve kitaplık için global işlem başına veriler içeren bir okuma-yazma segmenti (ne olduğunu bilmiyorum izinsiz segment; sadece x64 Linux'ta gördüm). Kütüphanenin salt okunur kısmı, kütüphaneyi kullanan tüm işlemler arasında paylaşılabilir; örneğin, libcpaylaşılabilen 1,5M sanal bellek alanına sahiptir.

Sanal Bellek Boyutu Ne Zaman Önemli?

Sanal bellek haritası birçok şey içeriyor. Bazıları salt okunurdur, bazıları paylaşılır ve bazıları tahsis edilir, ancak hiçbir zaman dokunulmaz (örneğin, bu örnekteki 4Gb yığınının neredeyse tamamı). Ancak işletim sistemi yalnızca ihtiyaç duyduğu şeyleri yükleyecek kadar akıllıdır, bu nedenle sanal bellek boyutu büyük ölçüde önemsizdir.

Sanal bellek boyutunun önemli olduğu yer, 32 bit işletim sisteminde çalışıyorsanız, yalnızca 2Gb (veya bazı durumlarda 3Gb) işlem adres alanı ayırabileceğiniz yerdir. Bu durumda, kıt bir kaynakla uğraşıyorsunuz ve büyük bir dosyayı bellekle eşleştirmek veya çok sayıda iş parçacığı oluşturmak için yığın boyutunuzu küçültmek gibi denemeler yapmak zorunda kalabilirsiniz.

Ancak, 64 bit makinelerin her yerde bulunduğu göz önüne alındığında, Sanal Bellek Boyutunun tamamen alakasız bir istatistik olması çok uzun süreceğini düşünmüyorum.

Yerleşik Set Boyutu ne zaman önemlidir?

Yerleşik Ayar boyutu, sanal bellek alanının gerçekte RAM olan bölümüdür. RSS'niz toplam fiziksel belleğinizin önemli bir parçası haline gelirse endişelenmeye başlamanın zamanı gelmiş olabilir. RSS'niz tüm fiziksel belleğinizi alacak şekilde büyürse ve sisteminiz değişmeye başlarsa, endişelenmeye başlamanın zamanı gelmiş demektir.

Ancak RSS, özellikle hafif yüklü bir makinede de yanıltıcıdır. İşletim sistemi, bir işlem tarafından kullanılan sayfaları geri almak için fazla çaba harcamaz. Bunu yaparak kazanılacak çok az fayda vardır ve işlem gelecekte sayfaya dokunursa pahalı bir sayfa hatası potansiyeli vardır. Sonuç olarak, RSS istatistiği aktif kullanımda olmayan çok sayıda sayfa içerebilir.

Sonuç olarak

Değiştirmediğiniz sürece, çeşitli bellek istatistiklerinin size ne söylediği konusunda aşırı endişelenmeyin. Sürekli büyüyen bir RSS'nin bir tür bellek sızıntısına işaret edebileceği uyarısı ile.

Bir Java programı ile, yığınta neler olduğuna dikkat etmek çok daha önemlidir. Tüketilen toplam alan miktarı önemlidir ve bunu azaltmak için atabileceğiniz bazı adımlar vardır. Daha da önemlisi, çöp toplamada harcadığınız zaman miktarı ve yığının hangi bölümlerinin toplandığıdır.

Diske (yani bir veritabanına) erişmek pahalıdır ve bellek ucuzdur. Birini diğeriyle takas edebiliyorsanız bunu yapın.


9
Şu anda takas edilen bellek bölümlerinin RES ölçüsünde eksik olduğunu dikkate almalısınız. Bu nedenle düşük bir RES değeriniz olabilir, ancak yalnızca uygulama etkin olmadığından ve yığının büyük bir kısmı diske değiştirildiğinden. Java takas etmek için çok kötü bir iş yapar: Her tam GC'de yığının çoğu yürür ve kopyalanır, böylece yığının çoğunun takas durumunda olması durumunda, GC hepsini ana belleğe yüklemelidir.
jrudolph

1
Harika cevap kdgregory! Takas alanı olmayan bir CF kullanarak gömülü bir ortamda çalışıyorum. Cevabınıza dayanarak tüm VIRT, SWAP ve nFLT değerlerim bellek eşlemeli dosyalardan ... şimdi mew için mantıklı. SWAP değerinin henüz belleğe yüklenmemiş sayfaları mı yoksa bellek dışı bırakılmış sayfaları mı yoksa her ikisini birden mi temsil ettiğini biliyor musunuz? Olası daralma hakkında nasıl bir fikir edinebiliriz (sürekli harita içeri sonra takas)?
Jeach

2
@Jeach - Ben herhangi bir takas rapor şaşırdım, bu yüzden benim "seyahat Linux" (Ubuntu 10.04 ile bir başparmak sürücü ve takas yok) çizdi. Üstte "SWAP" sütununu etkinleştirdiğimde Eclipse'in 509m olduğunu gördüm. Daha sonra pmap ile baktığımda toplam sanal alan 650m idi. Bu yüzden "SWAP" rakamının sadece bellekte olmayanları değil tüm diskteki sayfaları temsil ettiğinden şüpheleniyorum.
kdgregory

2
İkinci sorunuza gelince: sürekli olarak flash karttan sayfa okuyorsanız, G / Ç bekleme süreniz ( üstte özet olarak "% wa" olarak gösterilir) yüksek olmalıdır. Bununla birlikte, bunun özellikle herhangi bir etkinlik için yüksek olacağına dikkat edin (özellikle programınızın herhangi birini yaptığını varsayarak).
kdgregory

1
> 1M bloğu bir iplik yığınıdır; 4K bloğa ne girdiğini bilmiyorum. Ne okuma ne de yazma izinlerine sahip olarak işaretlenen 4K blok muhtemelen bir koruma bloğudur. Yığın taşması sırasında, JVM'nin daha sonra bir Java StackOverflowException oluşturarak işleyebileceği bir hatayı tetikleyen bu alana erişilir. Bu, her yöntem çağrısında yığın işaretçisini kontrol etmekten çok daha ucuzdur. İzinleri ayarlanmamış koruma alanları başka bağlamlarda da kullanılabilir.
eriksoe

38

Java ve glibc> = 2.10 ile ilgili bilinen bir sorun var (Ubuntu> = 10.04, RHEL> = 6'yı içerir).

Tedavisi bu ortamı ayarlamaktır. değişken:

export MALLOC_ARENA_MAX=4

Tomcat çalıştırıyorsanız, bunu TOMCAT_HOME/bin/setenv.shdosyaya ekleyebilirsiniz .

Docker için bunu Dockerfile'a ekleyin

ENV MALLOC_ARENA_MAX=4

MALLOC_ARENA_MAX ayarıyla ilgili bir IBM makalesi var https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=tr

Bu blog gönderisi diyor

yerleşik belleğin bir bellek sızıntısına veya bellek parçalanmasına benzer bir şekilde sürüldüğü bilinmektedir.

Ayrıca açık bir JDK hatası var JDK-8193521 "glibc varsayılan yapılandırmayla belleği boşa harcıyor"

daha fazla referans için MALLOC_ARENA_MAX'ı Google'da veya SO'da arayın.

Tahsis edilen belleğin düşük parçalanması için optimize etmek üzere diğer malloc seçeneklerini de ayarlamak isteyebilirsiniz:

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536

Bu cevap gerçekten "mem-tüketen" bir litte var bir TomEE sunucusu ile 64bit Ubuntu Sunucu bana yardımcı oldu. IBM makalesine bağlantı gerçekten derin bir açıklamadır. Bu iyi ipucu için tekrar teşekkürler!
MWiesner

1
JVM, benzer semptomlara yol açan doğal bellek sızdırabilir. Bkz. Stackoverflow.com/a/35610063/166062 . Kapatılmamış GZIPInputStream ve GZIPOutputStream örnekleri de sızıntının kaynağı olabilir.
Lari Hotari

3
Java 8'de sınırsız yerel bellek büyümesine neden olan bir JVM hatası var: bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8164293 - Bu sizi etkiliyorsa, MALLOC_ARENA_MAXbellek büyümenizi yavaşlatabilir, ancak sorunu tamamen çöz.
17'de outofcoffee

@LariHotari, glibc ve redhat versiyonunu gösterme çabalarınızı gerçekten takdir ediyor
Sam

2
Java 8u131, ilgili JVM hatası JDK-8164293 bugs.openjdk.java.net/browse/JDK-8178124 için backported hata düzeltmesi içerir .
Lari Hotari

9

Java işlemi için ayrılan bellek miktarı, beklediğim şeyle hemen hemen aynı. Katıştırılmış / bellek sınırlı sistemlerde Java'yı çalıştırırken benzer sorunlar yaşadım. Koşu herhangi keyfi VM sınırlarına veya takas yeterli miktarda yok sistemlerde uygulamayı kırmaya eğilimindedir. Kaynak sınırlı sistemlerde kullanılmak üzere tasarlanmamış birçok modern uygulamanın doğası gibi görünüyor.

JVM'nizin bellek kapladığı alanı deneyebileceğiniz ve sınırlandırabileceğiniz birkaç seçeneğiniz daha var. Bu sanal bellek kapladığı alanı azaltabilir:

-XX: ReservedCodeCacheSize = 32m Ayrılmış kod önbellek boyutu (bayt cinsinden) - maksimum kod önbellek boyutu. [Solaris 64 bit, amd64 ve -server x86: 48m; 1.5.0_06 ve öncesi, Solaris 64-bit ve ve64: 1024m.]

-XX: MaxPermSize = Kalıcı Nesilin 64m Boyutu. [5.0 ve daha yeni: 64 bit VM'ler% 30 daha büyük ölçeklenir; 1,4 amd64: 96m; 1.3.1 müşteri: 32m.]

Ayrıca, -Xmx'inizi (maks yığın boyutu) uygulamanızın gerçek maksimum bellek kullanımına mümkün olduğunca yakın bir değere ayarlamanız gerekir . Ben JVM varsayılan davranış hala max kadar her genişlettiğinde yığın boyutu iki katına olduğuna inanıyorum . 32M yığınla başlarsanız ve uygulamanız 65M'ye ulaşırsa, yığın 32M -> 64M -> 128M büyür.

VM'yi yığının büyümesi konusunda daha az agresif hale getirmek için de bunu deneyebilirsiniz:

-XX: MinHeapFreeRatio = 40 Genleşmeyi önlemek için GC'den sonra yığın boşluğunun minimum yüzdesi.

Ayrıca, birkaç yıl önce bunu denemekten hatırladığım kadarıyla, yüklenen yerel kütüphane sayısının minimum ayak izi üzerinde büyük bir etkisi oldu. Yükleme java.net.Socket doğru hatırlıyorsam 15 milyondan fazla ekledi (ve muhtemelen bilmiyorum).


7

Sun JVM, HotSpot için çok fazla bellek gerektirir ve paylaşılan bellekteki çalışma zamanı kitaplıklarında eşlenir.

Bellek bir sorunsa, gömme için uygun başka bir JVM kullanmayı düşünün. IBM'in j9'u vardır ve GNU sınıf yolu kitaplıklarını kullanan Açık Kaynak "jamvm" vardır. Ayrıca Sun'ın SunSPOTS üzerinde çalışan Squeak JVM'si var, bu yüzden alternatifler var.


Etkin noktayı devre dışı bırakmak için bir seçenek var mı?
Mario Ortegón

Belki. Kullandığınız JVM için komut satırı seçeneklerini kontrol edin.
Thorbjørn Ravn Andersen

3

Sadece bir düşünce, ama bir ulimit -vseçeneğin etkisini kontrol edebilirsiniz .

Bu, tüm işlem için kullanılabilir adres alanını sınırlayacağı için gerçek bir çözüm değildir , ancak uygulamanızın davranışını sınırlı bir sanal bellekle kontrol etmenizi sağlar.


Benim sorunum tam da bu. My Heap 64M olarak ayarlandı, ancak linux 204MB depolama alanı sunuyor. Ulimit'i 204'ün altına ayarlarsam, uygulama hiç çalışmaz.
Mario Ortegon

İlginç: ulimit'in ayarlanması, diğer işlemler için istenmeyen yan etkiye sahip olabilir ve uygulamanın neden çalışamadığını açıklar.
VonC

Sorun, Java'nın kullanmasa bile bu daha büyük miktarda Sanal belleği ayırması gerektiği gibi görünüyor. Pencerelerde kullanılan sanal bellek ve Xmx ayarı oldukça yakındır.
Mario Ortegon

JRockit JVM ile denediniz mi?
VonC

JVM'nin bellek ayırması Yığın Ayırma ve Perma Boyutu'nun toplamı olduğundan (ilki -Xms ve -Xmx seçenekleri kullanılarak sabitlenebilir), -XX: PermSize ve -XX: MaxPermSize ile bazı ayarları denediniz mi (varsayılan JVM sürümüne bağlı olarak 32MB - 64MB)?
VonC

3

Sınırlı kaynaklara sahip bir sistemin yığın sinyallerini azaltmanın bir yolu -XX: MaxHeapFreeRatio değişkeni ile oynamak olabilir. Bu genellikle 70 olarak ayarlanır ve GC küçülmeden önce yığının maksimum yüzdesidir. Daha düşük bir değere ayarladığınızda, örneğin jvisualvm profiler'de programınız için genellikle daha küçük bir yığın zarının kullanıldığını göreceksiniz.

EDIT: -XX: MaxHeapFreeRatio için küçük değerleri ayarlamak için de -XX: MinHeapFreeRatio Eg

java -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=25 HelloWorld

EDIT2: Aynı görevi başlatan ve aynı görevi gerçekleştiren gerçek bir uygulama için, biri varsayılan parametrelerle, diğeri ise 10 ve 25 ile parametreler için bir örnek eklendi. Teoride java ikinci örnekte yığını artırmak için daha fazla zaman kullanmasına rağmen, gerçek bir hız farkı fark etmedim.

Varsayılan parametreler

Sonunda, maksimum yığın 905, kullanılan yığın 378

MinHeap 10, MaxHeap 25

Sonunda, maksimum yığın 722, kullanılan yığın 378

Uygulamamız bir uzak masaüstü sunucusunda çalıştığından ve birçok kullanıcı aynı anda çalıştırabildiğinden, bunun aslında bir miktar etkisi vardır.


1

Sun'ın java 1.4'ü, bellek boyutunu kontrol etmek için aşağıdaki bağımsız değişkenlere sahiptir:

-Xmsn Bellek ayırma havuzunun başlangıç ​​boyutunu bayt olarak belirtir. Bu değer 1 MB'tan 1024'ün katları olmalıdır. Kilobaytı belirtmek için k veya K, megabaytı belirtmek için m veya M harfini ekleyin. Varsayılan değer 2 MB'dir. Örnekler:

           -Xms6291456
           -Xms6144k
           -Xms6m

-Xmxn Bellek ayırma havuzunun maksimum boyutunu bayt olarak belirtir. Bu değer, 2 MB'tan 1024'ün katları olmalıdır. Kilobaytı belirtmek için k veya K, megabaytı belirtmek için m veya M harfini ekleyin. Varsayılan değer 64 MB'dir. Örnekler:

           -Xmx83886080
           -Xmx81920k
           -Xmx80m

http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html

Java 5 ve 6'da biraz daha var. Bkz. Http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp


1
Sahip olduğum sorun Öbek Boyutu ile değil, Linux tarafından atanan Sanal Bellek miktarı ile
Mario Ortegón

Kdgregory'nin açıklamasını okuyun. Öbek boyutunu, "Yeni boyut" ve diğer yapılandırılabilir parametreleri azaltmak jvm'nin GERÇEK bellek miktarını azaltır.
Paul Tomblin

Meşru bir sorunu olabilir. Bazı uygulamalar (yazdığım gibi) 1 GB'lık bir dosyayı mmap ve bazı sistemlerde sadece 2 GB'lık sanal bellek var, bazıları paylaşılan kütüphanelerle doluyor. Ve eğer sorun buysa, DSO randomizasyonunu kesinlikle devre dışı bırakmalıdır. / Proc içinde bir seçenek vardır.
Zan Lynx

0

Hayır, VM için gereken bellek miktarını yapılandıramazsınız. Ancak, bunun sanal bellek olduğunu, yerleşik olmadığını unutmayın, bu yüzden aslında kullanılmazsa orada zarar görmeden kalır.

Dikkat çekici bir şekilde, daha küçük bellek ayak izi ile Sun'dan sonra başka bir JVM'yi deneyebilirsiniz, ancak burada tavsiye edemem.

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.