Batas overhead GC terlampaui

93

Berapa waktu pengambilan sampel yang digunakan JVM untuk menampilkan 'java.lang.OutOfMemoryError: batas overhead GC terlampaui'? Saya tahu Anda dapat mengontrol 98% dan 2% dengan parameter GCTimeLimit dan GCHeapFreeLimit tetapi apa waktu pengambilan sampelnya?

PRK
sumber

Jawaban:

82

Dari Java SE 6 HotSpot [tm] Tuning Pengumpulan Sampah Mesin Virtual

pengikut

GC Time dan OutOfMemoryError yang berlebihan

Kolektor serentak akan menampilkan OutOfMemoryError jika terlalu banyak waktu yang dihabiskan dalam pengumpulan sampah: jika lebih dari 98% dari total waktu dihabiskan untuk pengumpulan sampah dan kurang dari 2% dari heap dipulihkan, OutOfMemoryError akan dilemparkan. Fitur ini dirancang untuk mencegah aplikasi berjalan dalam waktu lama sementara hanya membuat sedikit atau tidak ada kemajuan karena heap terlalu kecil. Jika perlu, fitur ini dapat dinonaktifkan dengan menambahkan opsi -XX: -UseGCOverheadLimit ke baris perintah.

Kebijakannya sama dengan yang ada di kolektor paralel, kecuali waktu yang dihabiskan untuk melakukan koleksi serentak tidak dihitung dalam batas waktu 98%. Dengan kata lain, hanya pengumpulan yang dilakukan saat aplikasi dihentikan yang dihitung dalam waktu GC yang berlebihan. Koleksi semacam itu biasanya karena kegagalan mode bersamaan atau permintaan pengumpulan eksplisit (misalnya, panggilan ke System.gc ()).

dalam hubungannya dengan bagian bawah

Salah satu penggunaan pengumpulan sampah eksplisit yang paling sering ditemui terjadi dengan pengumpulan sampah terdistribusi (DGC) RMI. Aplikasi yang menggunakan RMI merujuk ke objek di mesin virtual lainnya. Sampah tidak dapat dikumpulkan dalam aplikasi yang didistribusikan ini tanpa terkadang mengumpulkan tumpukan lokal, jadi RMI memaksa pengumpulan penuh secara berkala. Frekuensi koleksi ini dapat dikontrol dengan properti. Sebagai contoh,

java -Dsun.rmi.dgc.client.gcInterval=3600000

-Dsun.rmi.dgc.server.gcInterval=3600000 menentukan koleksi eksplisit sekali per jam, bukan tarif default sekali per menit. Namun, hal ini juga dapat menyebabkan beberapa objek memerlukan waktu lebih lama untuk diklaim kembali. Properti ini dapat disetel setinggi Long.MAX_VALUE untuk membuat waktu antara koleksi eksplisit secara efektif tidak terbatas, jika tidak ada keinginan untuk batas atas ketepatan waktu aktivitas DGC.

Tampaknya menyiratkan bahwa periode evaluasi untuk menentukan 98% adalah satu menit, tetapi mungkin dapat dikonfigurasi pada JVM Sun dengan definisi yang benar.

Tentu saja, interpretasi lain dimungkinkan.

Edwin Buck
sumber
5
Pengumpulan sampah yang didistribusikan RMI merupakan kegiatan yang tidak terkait dengan pengumpulan sampah secara rutin. Jadi saya tidak mengerti bagaimana Anda bisa menyimpulkan apa yang baru saja Anda lakukan.
Stephen C
2
Kesimpulannya tidak sempurna atau bahkan benar, itulah mengapa "sepertinya menyiratkan" digunakan, bukan "menyiratkan". Jika Anda setuju dengan pengamatan bahwa jika orang-orang di Sun menggunakan satu menit dalam menentukan interval pengumpulan sampah untuk RMI, waktu pengumpulan dalam pengumpulan bersamaan hanya diakumulasikan ketika program utama berhenti, dan membuat sedikit lompatan keyakinan. , maka kemungkinan besar 98% dikumpulkan selama satu menit. Ini adalah angka ajaib, tetapi satu menit adalah angka ajaib yang sering digunakan sebagai perbandingan untuk mengatakan 3,5 menit.
Edwin Buck
@StephenC maksud Anda meskipun kami menyetelnya -XX:+DisableExplicitGC tidak akan memengaruhi konfigurasi terkait RMI dan sistem akan memanggil gc dalam frekuensi yang disetel dengan parameter-Dsun.rmi.dgc.server.gcInterval
Steephen
1
@ Steven - Tidak. Bukan itu yang saya katakan. Saya berbicara tentang pernyataan ini: "Sepertinya menyiratkan bahwa periode evaluasi untuk menentukan 98% adalah satu menit lama ..." . Dan perhatikan bahwa Edwin setuju bahwa kesimpulannya "tidak sempurna". Kesimpulan tersebut didasarkan pada asumsi bahwa orang-orang Sun yang menerapkan RMI (& DGC) berhubungan erat dengan orang-orang yang menerapkan mekanisme batas overhead GC. Saya menduga kedua perkembangan itu sebenarnya terjadi pada waktu yang berbeda. Perhatikan bahwa -Dsun.rmi.dgc.server.gcIntervalproperti ini sudah ada sejak Java 1.2.
Stephen C
1
Bagaimanapun, pendekatan yang lebih baik untuk menemukan jawaban sebenarnya untuk pertanyaan ini adalah dengan melihat kode sumber OpenJDK.
Stephen C