Java 5 üzerinde istemci taraflı bir Swing** uygulaması (grafik yazı tipi tasarımcısı) yazıyorum. Son zamanlarda, java.lang.OutOfMemoryError: Java heap space
hatası ile karşılaşıyorum çünkü bellek kullanımı konusunda tutucu davranmıyorum. Kullanıcı sınırsız sayıda dosya açabilir ve program açılan nesneleri bellekte tutar. Hızlı bir araştırmadan sonra Ergonomics in the 5.0 Java Virtual Machine ve Windows makinesinde JVM'nin varsayılan maksimum yığın boyutunun 64MB
olduğunu söyleyen başkalarını buldum.
Bu durum göz önüne alındığında, bu kısıtlamayla nasıl başa çıkmalıyım?
Java'nın komut satırı seçeneğini kullanarak maksimum yığın boyutunu artırabilirim, ancak bu mevcut RAM'i bulmayı ve bazı başlatma programı veya komut dosyası yazmayı gerektirir. Ayrıca, bir sonsuz maksimuma yükseltmek sonuçta sorunu ortadan kaldırmaz.
Belleği boşaltmak için kodumun bir kısmını nesneleri sık sık dosya sisteminde kalıcı hale getirecek şekilde yeniden yazabilirim (veritabanı kullanmak da aynı şeydir). İşe yarayabilir, ancak muhtemelen çok da fazla iş gerektirir.
Bana yukarıdaki fikirlerin ayrıntılarını veya otomatik sanal bellek, yığın boyutunu dinamik olarak genişletme gibi bazı alternatifleri gösterebilirseniz, bu harika olacaktır.
Sonuçta, hangi platformda çalışıyor olursanız olun her zaman kullanabileceğiniz sınırlı bir maksimum yığın vardır. Windows 32 bit'te bu 2GB
civarındadır (özellikle yığın değil, işlem başına toplam bellek miktarı). Sadece Java varsayılanı daha küçük yapmayı seçer (muhtemelen programcı bu sorunla karşılaşmadan ve tam olarak ne yaptıklarını incelemek zorunda kalmadan kaçak bellek tahsisine sahip programlar oluşturamaz).
Bu nedenle, ihtiyacınız olan bellek miktarını belirlemek ya da kullandığınız bellek miktarını azaltmak için uygulayabileceğiniz birkaç yaklaşım vardır. Java ya da C# gibi çöp toplayan dillerde sıkça yapılan hatalardan biri, artık kullanmadığınız nesnelerin referanslarını etrafta tutmak ya da yeniden kullanmak yerine çok sayıda nesne tahsis etmektir. Nesnelerin referansları olduğu sürece, çöp toplayıcı onları silmeyeceği için heap alanını kullanmaya devam edeceklerdir.
Bu durumda, programınızdaki hangi yöntemlerin çok sayıda nesne ayırdığını belirlemek için bir Java bellek profilleyicisi kullanabilir ve ardından artık bunlara başvurulmadığından emin olmanın veya ilk etapta bunları ayırmamanın bir yolu olup olmadığını belirleyebilirsiniz. Geçmişte kullandığım bir seçenek "JMP" http://www.khelekore.org/jmp/.
Bu nesneleri bir nedenle ayırdığınızı ve referansları etrafta tutmanız gerektiğini belirlerseniz (ne yaptığınıza bağlı olarak durum böyle olabilir), programı başlattığınızda maksimum yığın boyutunu artırmanız gerekecektir. Ancak, bellek profilini çıkardıktan ve nesnelerinizin nasıl tahsis edildiğini anladıktan sonra ne kadar belleğe ihtiyacınız olduğu konusunda daha iyi bir fikriniz olacaktır.
Genel olarak, programınızın sınırlı miktarda bellekte (belki de girdi boyutuna bağlı olarak) çalışacağını garanti edemezseniz, her zaman bu sorunla karşılaşırsınız. Ancak tüm bunları tükettikten sonra nesneleri diske önbelleğe alma vb. konulara bakmanız gerekecektir. Bu noktada, "Bir şey için Xgb belleğe ihtiyacım var" demek için çok iyi bir nedeniniz olmalı ve algoritmalarınızı veya bellek tahsis modellerinizi geliştirerek bunun üstesinden gelemezsiniz. Genelde bu durum sadece büyük veri kümeleri üzerinde çalışan algoritmalar (veritabanı ya da bilimsel analiz programı gibi) için geçerlidir ve bu durumda önbellekleme ve bellek eşlemeli IO gibi teknikler kullanışlı hale gelir.
Java'yı, yığının maksimum boyutunu ayarlayan komut satırı seçeneği -Xmx
ile çalıştırın.
Evet, -Xmx
ile JVM'niz için daha fazla bellek yapılandırabilirsiniz.
Bellek sızıntısı veya israfı yapmadığınızdan emin olmak için. Bir heap dökümü alın ve bellek tüketiminizi analiz etmek için Eclipse Memory Analyzer kullanın.