Apakah mungkin untuk memaksa pengumpulan sampah di Jawa, bahkan jika itu sulit dilakukan? Saya tahu System.gc();
dan Runtime.gc();
tetapi mereka hanya menyarankan untuk melakukan GC. Bagaimana saya bisa memaksakan GC?
java
garbage-collection
Robert Columbia
sumber
sumber
Jawaban:
Pilihan terbaik Anda adalah menelepon
System.gc()
yang hanya merupakan petunjuk bagi pengumpul sampah yang Anda inginkan untuk melakukan pengumpulan. Tidak ada cara untuk memaksa dan mengumpulkan segera karena pemulung tidak menentukan.sumber
non-deterministic == trouble
GC.Collect()
tidak mengumpulkan. Di Jawagc()
tidak.The jlibs perpustakaan memiliki kelas utilitas yang baik untuk pengumpulan sampah . Anda dapat memaksa pengumpulan sampah menggunakan sedikit trik bagus dengan objek WeakReference .
RuntimeUtil.gc () dari jlibs:
sumber
PhantomReference
denganReferenceQueue
dan kemudian Anda akan diberi tahu setelah finalisasi, tetapi masih sebelum pembersihan. Akhirnya, bahkan jika Anda berhasil mendeteksi bahwa memori untuk objek ini direklamasi, itu masih berarti sangat sedikit dalam GC generasi seperti HotSpot. Biasanya itu akan bertepatan dengan pembersihan generasi muda.System.gc(); System.gc();
, tetapi tentu akan menarik untuk mengetahui apakah itu pernah bekerja lebih baik dari itu. Bahkan, hanya mencetak berapa kali disebutSystem.gc()
sudah cukup. Peluang untuk mencapai 2 cukup tipis.Cara terbaik (jika tidak hanya) untuk memaksa GC adalah dengan menulis JVM khusus. Saya percaya para pengumpul Sampah bisa dicolokkan sehingga Anda mungkin bisa memilih salah satu implementasi yang tersedia dan mengubahnya.
Catatan: Ini BUKAN jawaban yang mudah.
sumber
Menggunakan Java ™ Virtual Machine Tool Interface (JVM TI) , fungsinya
akan "Memaksa VM untuk melakukan pengumpulan sampah." JVM TI adalah bagian dari Platform Java Debugger Architecture (JPDA) .
sumber
YA hampir mungkin memaksa Anda harus memanggil metode dengan urutan yang sama dan pada saat yang sama ini adalah:
bahkan jika hanya satu objek untuk membersihkan penggunaan kedua metode ini pada saat yang sama memaksa pemulung untuk menggunakan
finalise()
metode objek yang tidak terjangkau membebaskan memori yang ditugaskan dan melakukan apa yangfinalize()
dinyatakan oleh metode.NAMUN merupakan praktik yang mengerikan untuk menggunakan pengumpul sampah karena penggunaannya dapat memperkenalkan kelebihan beban ke perangkat lunak yang mungkin bahkan lebih buruk daripada pada memori, pengumpul sampah memiliki utas sendiri yang tidak mungkin untuk dikontrol plus tergantung pada algoritma yang digunakan oleh gc bisa memakan waktu lebih lama dan dianggap sangat tidak efisien, Anda harus memeriksa perangkat lunak Anda jika terburuk dengan bantuan gc karena sudah pasti rusak, solusi yang baik tidak boleh bergantung pada gc.
CATATAN: hanya untuk diingat ini hanya akan berfungsi jika dalam metode finalisasi bukan penugasan kembali objek, jika ini terjadi objek akan tetap hidup dan akan memiliki kebangkitan yang secara teknis memungkinkan.
sumber
gc()
hanya isyarat untuk menjalankan pengumpulan sampah.runFinalizers()
hanya menjalankan finalizer pada objek "yang telah ditemukan dibuang". Jika gc tidak benar-benar berjalan, mungkin tidak ada objek seperti itu ...Di bawah dokumentasi untuk OutOfMemoryError ia menyatakan bahwa itu tidak akan dibuang kecuali VM telah gagal untuk mendapatkan kembali memori setelah pengumpulan sampah penuh. Jadi, jika Anda terus mengalokasikan memori hingga Anda mendapatkan kesalahan, Anda sudah akan terpaksa mengumpulkan sampah penuh.
Mungkin pertanyaan yang benar-benar ingin Anda tanyakan adalah "bagaimana saya bisa mendapatkan kembali memori yang saya pikir saya harus reklamasi dengan pengumpulan sampah?"
sumber
Untuk Meminta GC secara manual (bukan dari System.gc ()):
sumber
.gc adalah kandidat untuk eliminasi dalam rilis mendatang - Insinyur Sun pernah berkomentar bahwa mungkin kurang dari dua puluh orang di dunia yang benar-benar tahu cara menggunakan .gc () - Saya melakukan pekerjaan tadi malam selama beberapa jam di pusat / kritis struktur data menggunakan data yang dihasilkan SecureRandom, di suatu tempat hanya melewati 40.000 objek vm akan melambat seolah-olah kehabisan pointer. Jelas itu tersedak tabel pointer 16-bit dan menunjukkan perilaku "mesin gagal" klasik.
Saya mencoba -Xms dan seterusnya, terus sedikit memutar-mutar sampai berjalan sekitar 57, xxx sesuatu. Maka itu akan menjalankan gc dari mengatakan 57.127 menjadi 57.128 setelah gc () - sekitar kecepatan code-bloat di camp Easy Money.
Desain Anda perlu dikerjakan ulang secara mendasar, mungkin pendekatan jendela geser.
sumber
Anda dapat memicu GC dari baris perintah. Ini berguna untuk batch / crontab:
Lihat :
sumber
Spesifikasi JVM tidak mengatakan sesuatu yang spesifik tentang pengumpulan sampah. Karena itu, vendor bebas menerapkan GC dengan cara mereka.
Jadi ketidakjelasan ini menyebabkan ketidakpastian dalam perilaku pengumpulan sampah. Anda harus memeriksa detail JVM Anda untuk mengetahui tentang pendekatan / algoritma pengumpulan sampah. Juga ada opsi untuk menyesuaikan perilaku.
sumber
Jika Anda perlu memaksakan pengumpulan sampah, mungkin Anda harus mempertimbangkan bagaimana Anda mengelola sumber daya. Apakah Anda membuat objek besar yang bertahan dalam memori? Apakah Anda membuat objek besar (misalnya, kelas grafis) yang memiliki
Disposable
antarmuka dan tidak memanggildispose()
ketika selesai dengannya? Apakah Anda mendeklarasikan sesuatu di tingkat kelas yang hanya Anda perlukan dalam satu metode?sumber
Akan lebih baik jika Anda menjelaskan alasan mengapa Anda membutuhkan pengumpulan sampah. Jika Anda menggunakan SWT, Anda dapat membuang sumber daya seperti
Image
danFont
untuk membebaskan memori. Misalnya:Ada juga alat untuk menentukan sumber daya yang tidak diinginkan.
sumber
Jika Anda kehabisan memori dan mendapatkan yang
OutOfMemoryException
Anda dapat mencoba meningkatkan jumlah ruang tumpukan yang tersedia untuk java dengan memulai program Anda denganjava -Xms128m -Xmx512m
bukan hanyajava
. Ini akan memberi Anda ukuran tumpukan awal 128Mb dan maksimum 512Mb, yang jauh lebih dari standar 32Mb / 128Mb.sumber
java -Xms512M -Xmx1024M
Pilihan lain adalah tidak membuat objek baru.
Penyatuan objek jauh untuk mengurangi kebutuhan GC di Jawa.
Pengumpulan objek umumnya tidak akan lebih cepat dari Pembuatan objek (terutama untuk objek ringan) tetapi lebih cepat dari Pengumpulan Sampah. Jika Anda membuat 10.000 objek dan setiap objek adalah 16 byte. 160.000 byte GC harus diperoleh kembali. Di sisi lain, jika Anda tidak membutuhkan semua 10.000 pada saat yang sama, Anda dapat membuat kumpulan untuk mendaur ulang / menggunakan kembali objek yang menghilangkan kebutuhan untuk membangun objek baru dan menghilangkan kebutuhan untuk GC objek lama.
Sesuatu seperti ini (belum diuji). Dan jika Anda menginginkannya aman, Anda dapat menukar keluar LinkedList dengan ConcurrentLinkedQueue.
sumber
Pada OracleJDK 10 dengan G1 GC, satu panggilan ke
System.gc()
akan menyebabkan GC membersihkan Koleksi Lama. Saya tidak yakin apakah GC langsung berjalan. Namun, GC tidak akan membersihkan Young Collection bahkan jikaSystem.gc()
dipanggil berkali-kali dalam satu lingkaran. Untuk mendapatkan GC untuk membersihkan Koleksi Muda, Anda harus mengalokasikan dalam satu lingkaran (mis.new byte[1024]
) Tanpa meneleponSystem.gc()
. MeneleponSystem.gc()
untuk beberapa alasan mencegah GC dari membersihkan Young Collection.sumber
Ini benar, hanya isyarat. Anda memiliki cukup banyak jawaban standar yang sudah diberikan oleh beberapa poster. Mari kita ambil satu per satu ini:
Benar, tidak ada jvm yang sebenarnya - hanya ada spesifikasi, sekelompok ilmu komputer yang menggambarkan perilaku yang diinginkan ... Saya baru saja menggali untuk menginisialisasi objek Java dari kode asli. Untuk mendapatkan apa yang Anda inginkan, satu-satunya cara adalah melakukan apa yang disebut agresif nulling. Kesalahan jika dilakukan salah begitu buruk sehingga kita harus membatasi diri pada lingkup asli dari pertanyaan:
Sebagian besar poster di sini akan menganggap Anda mengatakan Anda bekerja pada sebuah antarmuka, jika demikian kami harus melihat apakah Anda sedang menyerahkan seluruh objek atau satu item pada suatu waktu.
Jika Anda tidak lagi membutuhkan objek, Anda dapat menetapkan null ke objek tetapi jika Anda salah ada pengecualian null pointer yang dihasilkan. Saya yakin Anda dapat mencapai pekerjaan yang lebih baik jika Anda menggunakan NIO
Setiap kali Anda atau saya atau orang lain mendapatkan: " Tolong saya sangat membutuhkannya. " Ini hampir merupakan prekursor universal untuk kehancuran total yang hampir sama dengan apa yang Anda coba kerjakan .... tulis kami kode sampel kecil, bersihkan dari apa pun kode aktual yang digunakan dan tunjukkan pertanyaan Anda kepada kami.
Jangan frustrasi. Seringkali apa yang dipecahkan adalah dBA Anda menggunakan paket yang dibeli di suatu tempat dan desain aslinya tidak diubah untuk struktur data yang besar.
Itu sangat umum.
sumber
FYI
Pemanggilan metode System.runFinalizersOnExit (true) menjamin bahwa metode finalizer dipanggil sebelum Java dimatikan. Namun, metode ini secara inheren tidak aman dan telah usang. Alternatifnya adalah menambahkan "shutdown hooks" dengan metode Runtime.addShutdownHook.
Masarrat Siddiqui
sumber
Ada beberapa cara tidak langsung untuk memaksa pemulung. Anda hanya perlu mengisi tumpukan dengan benda-benda sementara sampai titik ketika pengumpul sampah akan mengeksekusi. Saya telah membuat kelas yang memaksa pemulung dengan cara ini:
Pemakaian:
Saya tidak tahu berapa banyak metode ini berguna, karena mengisi tumpukan terus-menerus, tetapi jika Anda memiliki aplikasi misi kritis yang HARUS memaksa GC - saat ini mungkin cara portabel Java untuk memaksa GC.
sumber
Saya ingin menambahkan sesuatu di sini. Tolong bukan bahwa Java berjalan pada Mesin Virtual dan bukan Mesin yang sebenarnya. Mesin virtual memiliki cara komunikasi sendiri dengan mesin. Ini mungkin bervariasi dari satu sistem ke sistem lainnya. Sekarang Ketika kita memanggil GC kita meminta Mesin Virtual Java untuk memanggil Pengumpul Sampah.
Karena Pengumpul Sampah menggunakan Mesin Virtual, kami tidak dapat memaksanya melakukan pembersihan di sana dan kemudian. Sebaliknya, kami mengantri permintaan kami dengan Pengumpul Sampah. Itu tergantung pada Mesin Virtual, setelah waktu tertentu (ini dapat berubah dari sistem ke sistem, umumnya ketika ambang memori yang dialokasikan untuk JVM penuh) mesin yang sebenarnya akan membebaskan ruang. : D
sumber
Kode berikut diambil dari metode assertGC (...). Ini mencoba untuk memaksa pengumpul sampah nondeterministic untuk mengumpulkan.
Sumber (saya menambahkan beberapa komentar untuk kejelasan): Contoh NbTestCase
sumber
Anda dapat mencoba menggunakan
Runtime.getRuntime().gc()
atau menggunakan metode utilitasSystem.gc()
Catatan: Metode ini tidak memastikan GC. Dan ruang lingkup mereka harus dibatasi pada JVM daripada secara terprogram menangani aplikasi Anda.sumber
Jika Anda menggunakan JUnit dan Spring, coba tambahkan ini di setiap kelas tes:
sumber