java.lang.OutOfMemoryError: ruang heap Java

97

Saya mendapatkan pesan kesalahan berikut saat menjalankan program multi-threading

java.lang.OutOfMemoryError: Java heap space

Kesalahan di atas terjadi di salah satu utas.

  1. Sepengetahuan saya, ruang Heap ditempati oleh variabel instan saja. Jika ini benar, lalu mengapa kesalahan ini terjadi setelah berjalan dengan baik untuk beberapa waktu karena ruang untuk variabel contoh dialokasikan pada saat pembuatan objek.

  2. Apakah ada cara untuk menambah ruang heap?

  3. Perubahan apa yang harus saya lakukan pada program saya sehingga Program ini akan mengambil lebih sedikit ruang heap?

Yatendra Goel
sumber

Jawaban:

105

Jika Anda ingin menambah ruang heap, Anda dapat menggunakan java -Xms<initial heap size> -Xmx<maximum heap size>di baris perintah. Secara default, nilai didasarkan pada versi JRE dan konfigurasi sistem. Anda dapat mengetahui lebih lanjut tentang opsi VM di situs web Java .

Namun, saya akan merekomendasikan membuat profil aplikasi Anda untuk mencari tahu mengapa ukuran heap Anda dimakan. NetBeans memiliki profiler yang sangat bagus yang disertakan dengannya. Saya percaya itu menggunakan di jvisualvmbawah tenda. Dengan profiler, Anda dapat mencoba menemukan di mana banyak objek dibuat, kapan objek dikumpulkan sampah, dan banyak lagi.

Thomas Owens
sumber
1
Saya menggunakan Netbeans tetapi saya tidak tahu cara menggunakan profiler. Saya ingin mengetahui lebih banyak tentang profiler sehingga saya dapat menggunakannya untuk menemukan kebocoran memori dalam aplikasi saya.
Yatendra Goel
Saya menambahkan link ke halaman di situs NetBeans ( profiler.netbeans.org ) yang memiliki dokumentasi yang sangat bagus tentang profil tersebut, dari yang paling dasar hingga penggunaan yang lebih canggih.
Thomas Owens
Nilai default berubah dengan versi java, alangkah baiknya untuk menyertakan informasi ini dalam jawaban Anda.
Dariusz
Baru saja memperbaiki masalah yang sama dan pertama kali mencoba: java -jar division.jar -Xmx512m -Xms512m - ini memberi saya kesalahan yang sama tetapi ketika saya melakukannya seperti ini: java -Xmx512m -Xms512m -jar division.jar - semuanya baik-baik saja. Jadi urutan params juga penting.
hipokito
@hipokito Argumen setelah file jar diteruskan ke metode main () file jar sebagai args []
Asu
29

1.- Ya, tetapi ini cukup banyak mengacu pada seluruh memori yang digunakan oleh program Anda.

2.- Ya, lihat opsi Java VM

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

Yaitu

java -Xmx2g tetapkan 2 gigabyte ram sebagai maksimum untuk aplikasi Anda

Tetapi Anda harus melihat apakah Anda tidak mengalami kebocoran memori terlebih dahulu.

3.- Itu tergantung pada programnya. Coba kebocoran memori spot. Pertanyaan ini akan sulit dijawab. Akhir-akhir ini Anda dapat membuat profil menggunakan JConsole untuk mencoba mencari tahu kemana tujuan ingatan Anda

OscarRyz
sumber
sementara yang (benar);)
Gal Bracha
8

Anda mungkin ingin melihat situs ini untuk mempelajari lebih lanjut tentang memori di JVM: http://developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage

Saya merasa berguna menggunakan visualgc untuk melihat bagaimana bagian-bagian berbeda dari model memori terisi, untuk menentukan apa yang harus diubah.

Sulit untuk menentukan bagian mana dari memori yang terisi, oleh karena itu visualgc, karena Anda mungkin ingin mengubah bagian yang bermasalah, daripada hanya mengatakan,

Baik! Saya akan memberikan 1G RAM ke JVM.

Cobalah untuk lebih tepat tentang apa yang Anda lakukan, dalam jangka panjang Anda mungkin akan menemukan program yang lebih baik untuk itu.

Untuk menentukan di mana kebocoran memori mungkin Anda dapat menggunakan tes unit untuk itu, dengan menguji apa memori sebelum tes, dan setelahnya, dan jika ada perubahan yang terlalu besar maka Anda mungkin ingin memeriksanya, tetapi, Anda perlu lakukan pemeriksaan saat pengujian Anda masih berjalan.

James Black
sumber
6

Untuk meningkatkan ukuran heap, Anda bisa menggunakan argumen -Xmx saat memulai Java; misalnya

-Xmx256M
Adamski
sumber
6

Anda bisa mendapatkan ukuran memori heap melalui program di bawah ini.

public class GetHeapSize {
    public static void main(String[] args) {
        long heapsize = Runtime.getRuntime().totalMemory();
        System.out.println("heapsize is :: " + heapsize);
    }
} 

maka Anda juga dapat meningkatkan ukuran heap dengan menggunakan: java -Xmx2g http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

pengguna2663609
sumber
6
  1. Sepengetahuan saya, ruang Heap ditempati oleh variabel instan saja. Jika ini benar, lalu mengapa kesalahan ini terjadi setelah berjalan dengan baik untuk beberapa waktu karena ruang untuk variabel contoh dialokasikan pada saat pembuatan objek.

Itu berarti Anda membuat lebih banyak objek dalam aplikasi Anda selama periode waktu tertentu secara terus menerus. Objek baru akan disimpan dalam memori heap dan itulah alasan pertumbuhan memori heap.

Heap tidak hanya berisi variabel instance. Ini akan menyimpan semua tipe data non-primitif (Objek). Umur objek ini mungkin pendek (blok metode) atau panjang (sampai objek direferensikan dalam aplikasi Anda)

  1. Apakah ada cara untuk menambah ruang heap?

Iya. Lihat artikel oracle ini untuk lebih jelasnya.

Ada dua parameter untuk menyetel ukuran heap:

-Xms : , yang menetapkan ukuran heap awal dan minimum

-Xmx:, yang menyetel ukuran heap maksimum

  1. Perubahan apa yang harus saya lakukan pada program saya sehingga Program ini akan mengambil lebih sedikit ruang heap?

Itu tergantung pada aplikasi Anda.

  1. Setel memori heap maksimum sesuai kebutuhan aplikasi Anda

  2. Jangan menyebabkan kebocoran memori di aplikasi Anda

  3. Jika Anda menemukan kebocoran memori dalam aplikasi Anda, temukan akar masalah dengan bantuan alat pembuatan profil seperti MAT , Visual VM , jconsole , dll. Setelah Anda menemukan akar penyebabnya, perbaiki kebocoran tersebut.

Catatan penting dari artikel oracle

Penyebab: Pesan detail Java heap space menunjukkan bahwa objek tidak dapat dialokasikan di heap Java. Kesalahan ini tidak selalu berarti kebocoran memori.

Kemungkinan alasan:

  1. Konfigurasi yang tidak tepat (tidak mengalokasikan memori yang memadai)
  2. Aplikasi secara tidak sengaja menyimpan referensi ke objek dan ini mencegah objek dikumpulkan dari sampah
  3. Aplikasi yang menggunakan bahan finalisator secara berlebihan. Jika sebuah kelas memiliki metode penyelesaian, maka objek jenis itu tidak memiliki ruangnya yang diperoleh kembali pada waktu pengumpulan sampah. Jika thread finalizer tidak dapat mengikuti, dengan antrian finalisasi, maka heap Java dapat terisi dan jenis pengecualian OutOfMemoryError ini akan dilempar .

Pada catatan yang berbeda, gunakan algoritma pengumpulan Sampah yang lebih baik ( CMS atau G1GC )

Lihat pertanyaan ini untuk memahami G1GC

Ravindra babu
sumber
5
  1. Dalam kebanyakan kasus, kode tidak dioptimalkan. Lepaskan benda-benda yang menurut Anda tidak akan dibutuhkan lebih lanjut. Hindari pembuatan objek di loop Anda setiap kali. Coba gunakan cache. Saya tidak tahu bagaimana kinerja aplikasi Anda. Tetapi dalam pemrograman, satu aturan kehidupan normal juga berlaku

    Mencegah lebih baik daripada mengobati. "Jangan membuat objek yang tidak perlu"

DKSRathore
sumber
3
  1. Variabel lokal terletak di tumpukan. Ruang heap ditempati oleh objek.

  2. Anda dapat menggunakan -Xmxopsi.

  3. Pada dasarnya ruang heap digunakan setiap kali Anda mengalokasikan objek baru dengan newdan dikosongkan beberapa saat setelah objek tidak lagi direferensikan. Jadi, pastikan Anda tidak menyimpan referensi ke objek yang tidak lagi Anda perlukan.

sepp2k.dll
sumber
1

Tidak, saya pikir Anda memikirkan ruang tumpukan. Ruang heap ditempati oleh objek. Cara untuk meningkatkannya adalah -Xmx256m, menggantikan 256 dengan jumlah yang Anda butuhkan pada baris perintah.

Yishai
sumber
1

Untuk menghindari pengecualian itu, jika Anda menggunakan JUnit dan Spring, coba tambahkan ini di setiap kelas pengujian:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
Aliuk
sumber
0

Di netbeans, Buka toolbar 'Run', -> 'Set Project Configuration' -> 'Customize' -> 'run' dari windo yang muncul -> 'VM Option' -> isi '-Xms2048m -Xmx2048m '. Itu bisa memecahkan masalah ukuran tumpukan.

Xiaogang
sumber