Bagaimana Anda menemukan kebocoran memori di Java (menggunakan, misalnya, JHat)? Saya telah mencoba memuat tumpukan heap di JHat untuk melihat dasar. Namun, saya tidak mengerti bagaimana saya seharusnya dapat menemukan referensi root ( ref ) atau apa pun namanya. Pada dasarnya, saya dapat mengatakan bahwa ada beberapa ratus megabyte entri tabel hash ([java.util.HashMap $ Entri atau sesuatu seperti itu), tetapi peta digunakan di semua tempat ... Apakah ada cara untuk mencari peta besar , atau mungkin menemukan akar umum dari pohon objek besar?
[Sunting] Ok, saya sudah membaca jawabannya sejauh ini tetapi katakan saja saya bajingan yang murah (artinya saya lebih tertarik mempelajari cara menggunakan JHat daripada membayar untuk JProfiler). Selain itu, JHat selalu tersedia karena merupakan bagian dari JDK. Kecuali tentu saja tidak ada cara dengan JHat selain kekerasan, tapi aku tidak percaya itu bisa terjadi.
Juga, saya tidak berpikir saya akan dapat benar-benar memodifikasi (menambahkan logging dari semua ukuran peta) dan menjalankannya cukup lama untuk saya perhatikan kebocorannya.
sumber
Jawaban:
Saya menggunakan pendekatan berikut untuk menemukan kebocoran memori di Jawa. Saya telah menggunakan jProfiler dengan sangat sukses, tetapi saya percaya bahwa setiap alat khusus dengan kemampuan grafik (diffs lebih mudah untuk dianalisis dalam bentuk grafis) akan berfungsi.
Pada dasarnya analisis harus dimulai dari perbedaan positif terbesar dengan, katakanlah, jenis-jenis objek dan temukan apa yang menyebabkan objek-objek ekstra itu melekat di memori.
Untuk aplikasi web yang memproses permintaan dalam beberapa analisis utas menjadi lebih rumit, namun demikian pendekatan umum masih berlaku.
Saya melakukan sejumlah proyek yang secara khusus bertujuan mengurangi jejak memori aplikasi dan pendekatan umum ini dengan beberapa penyesuaian dan trik khusus aplikasi selalu bekerja dengan baik.
sumber
Penanya di sini, saya harus mengatakan mendapatkan alat yang tidak membutuhkan waktu 5 menit untuk menjawab klik apa pun membuatnya lebih mudah untuk menemukan potensi kebocoran memori.
Karena orang menyarankan beberapa alat (saya hanya mencoba visual wm sejak saya mendapatkannya dalam uji coba JDK dan JProbe) saya pikir saya harus menyarankan alat sumber bebas / terbuka yang dibangun pada platform Eclipse, Memory Analyzer (kadang-kadang disebut sebagai memori SAP analyzer) tersedia di http://www.eclipse.org/mat/ .
Apa yang benar-benar keren tentang alat ini adalah mengindeks tumpukan heap ketika saya pertama kali membukanya yang memungkinkannya untuk menampilkan data seperti retakan heap tanpa menunggu 5 menit untuk setiap objek (hampir semua operasi adalah ton lebih cepat daripada alat lain yang saya coba) .
Saat Anda membuka tempat sampah, layar pertama menampilkan bagan pai dengan objek terbesar (menghitung tumpukan yang tersisa) dan seseorang dapat dengan cepat menavigasi ke objek yang besar untuk kenyamanan. Ini juga memiliki Temukan kemungkinan kebocoran yang menurut saya bisa berguna, tetapi karena navigasi sudah cukup bagi saya, saya tidak benar-benar masuk ke dalamnya.
sumber
HeapDumpOnCtrlBreak
parameter VM tidak tersedia . Solusi yang saya temukan (sejauh ini, masih mencari) adalah dengan menggunakan JMap untuk membuang.hprof
file, yang kemudian saya masukkan ke Eclipse dan gunakan MAT untuk memeriksa.Alat adalah bantuan besar.
Namun, ada kalanya Anda tidak dapat menggunakan alat: tumpukan timbunan sangat besar sehingga merusak alat, Anda mencoba memecahkan masalah mesin di beberapa lingkungan produksi yang Anda hanya memiliki akses shell, dll.
Dalam hal ini, ada baiknya untuk mengetahui cara Anda di sekitar file dump hprof.
Cari SITUS DIMULAI. Ini menunjukkan objek apa yang paling banyak menggunakan memori. Tetapi objek tidak disatukan bersama hanya berdasarkan tipe: setiap entri juga menyertakan ID "jejak". Anda kemudian dapat mencari "TRACE nnnn" untuk melihat beberapa frame teratas dari tumpukan tempat objek dialokasikan. Seringkali, begitu saya melihat di mana objek dialokasikan, saya menemukan bug dan saya selesai. Juga, perhatikan bahwa Anda dapat mengontrol berapa banyak frame yang direkam dalam tumpukan dengan opsi untuk -Xrunhprof.
Jika Anda memeriksa situs alokasi, dan tidak melihat ada yang salah, Anda harus mulai merantai ke belakang dari beberapa objek langsung ke root objek, untuk menemukan rantai referensi yang tidak terduga. Di sinilah alat sangat membantu, tetapi Anda dapat melakukan hal yang sama dengan tangan (well, with grep). Tidak hanya ada satu objek root (yaitu, objek tidak tunduk pada pengumpulan sampah). Thread, kelas, dan bingkai stack bertindak sebagai objek root, dan apa pun yang mereka referensikan kuat tidak dapat dikoleksi.
Untuk melakukan chaining, lihat di bagian HEAP DUMP untuk entri dengan id jejak buruk. Ini akan membawa Anda ke entri OBJ atau ARR, yang menunjukkan pengidentifikasi objek unik dalam heksadesimal. Cari semua kemunculan id itu untuk menemukan siapa yang punya referensi kuat ke objek tersebut. Ikuti setiap jalan ke belakang saat mereka bercabang sampai Anda mengetahui di mana kebocorannya. Lihat mengapa alat sangat berguna?
Anggota statis adalah pelanggar berulang karena kebocoran memori. Bahkan, bahkan tanpa alat, itu akan bernilai menghabiskan beberapa menit melihat kode Anda untuk anggota Peta statis. Bisakah peta menjadi besar? Apakah ada yang pernah membersihkan entri?
sumber
jhat
danMAT
tampaknya mencoba memuat seluruh heap dump ke dalam memori, dan biasanya menabrakOutOfMemoryError
pada dump besar (yaitu, dari aplikasi yang paling membutuhkan analisis tumpukan! ). NetBeans Profiler tampaknya menggunakan algoritma yang berbeda untuk mengindeks referensi yang bisa lambat pada dump besar tetapi setidaknya tidak mengkonsumsi memori tidak terbatas dalam alat dan crash.Sebagian besar waktu, dalam aplikasi perusahaan tumpukan Java yang diberikan lebih besar dari ukuran ideal maksimal 12 hingga 16 GB. Saya merasa sulit untuk membuat profiler NetBeans bekerja langsung pada aplikasi-aplikasi java besar ini.
Tetapi biasanya ini tidak diperlukan. Anda dapat menggunakan utilitas jmap yang datang dengan jdk untuk mengambil heap dump "hidup", yaitu jmap akan membuang heap setelah menjalankan GC. Lakukan beberapa operasi pada aplikasi, tunggu sampai operasi selesai, lalu ambil tumpukan heap "langsung". Gunakan alat seperti Eclipse MAT untuk memuat heapdumps, mengurutkan pada histogram, melihat objek mana yang telah meningkat, atau mana yang tertinggi, Ini akan memberikan petunjuk.
Hanya ada satu masalah dengan pendekatan ini; Tumpukan tumpukan besar, bahkan dengan opsi live, mungkin terlalu besar untuk dipindahkan ke putaran pengembangan, dan mungkin memerlukan mesin dengan memori / RAM yang cukup untuk dibuka.
Di situlah histogram kelas muncul. Anda dapat membuang histogram kelas langsung dengan alat jmap. Ini hanya akan memberikan histogram kelas penggunaan memori. Pada dasarnya itu tidak akan memiliki informasi untuk rantai referensi. Sebagai contoh dapat menempatkan array char di bagian atas. Dan kelas String di suatu tempat di bawah ini. Anda harus menggambar koneksi sendiri.
Alih-alih mengambil dua heap dump, ambil dua histogram kelas, seperti yang dijelaskan di atas; Kemudian membandingkan histogram kelas dan melihat kelas-kelas yang meningkat. Lihat apakah Anda dapat menghubungkan kelas Java ke kelas aplikasi Anda. Ini akan memberikan petunjuk yang cukup bagus. Berikut ini adalah skrip python yang dapat membantu Anda membandingkan dua dump histogram jmap. histogramparser.py
Akhirnya alat seperti JConolse dan VisualVm sangat penting untuk melihat pertumbuhan memori dari waktu ke waktu, dan melihat apakah ada kebocoran memori. Akhirnya kadang-kadang masalah Anda mungkin bukan kebocoran memori, tetapi penggunaan memori yang tinggi. Untuk ini memungkinkan GC logging, gunakan GC pemadatan yang lebih maju dan baru seperti G1GC; dan Anda dapat menggunakan alat jdk seperti jstat untuk melihat langsung perilaku GC
Referensi lain ke google untuk -jhat, jmap, GC Penuh, alokasi Humongous, G1GC
sumber
Ada alat yang akan membantu Anda menemukan kebocoran Anda, seperti JProbe, YourKit, AD4J atau JRockit Mission Control. Yang terakhir adalah yang paling saya kenal secara pribadi. Alat apa pun yang baik harus membiarkan Anda menelusuri ke tingkat di mana Anda dapat dengan mudah mengidentifikasi kebocoran apa, dan di mana objek bocor dialokasikan.
Menggunakan HashTables, Hashmaps atau yang serupa adalah salah satu dari beberapa cara Anda dapat membocorkan memori di Java secara bersamaan. Jika saya harus menemukan kebocoran dengan tangan saya akan mencetak ukuran HashMaps saya, dan dari sana menemukan yang mana saya menambahkan item dan lupa untuk menghapusnya.
sumber
Ya, selalu ada solusi berteknologi rendah untuk menambahkan pencatatan ukuran peta Anda saat Anda memodifikasinya, lalu cari log yang petanya tumbuh melebihi ukuran yang wajar.
sumber
NetBeans memiliki profiler bawaan.
sumber
Anda benar-benar perlu menggunakan profiler memori yang melacak alokasi. Lihatlah JProfiler - fitur "heap walker" mereka sangat bagus, dan mereka memiliki integrasi dengan semua IDE Java utama. Ini tidak gratis, tetapi juga tidak semahal itu ($ 499 untuk satu lisensi) - Anda akan menghabiskan waktu senilai $ 500 dengan cepat berjuang untuk menemukan kebocoran dengan alat yang kurang canggih.
sumber
Anda dapat mengetahuinya dengan mengukur ukuran penggunaan memori setelah memanggil pengumpul sampah beberapa kali:
Jika nomor output sama, tidak ada kebocoran memori dalam aplikasi Anda, tetapi jika Anda melihat perbedaan antara jumlah penggunaan memori (semakin banyak), ada kebocoran memori di proyek Anda. Sebagai contoh:
Perhatikan bahwa terkadang diperlukan waktu untuk melepaskan memori dengan beberapa tindakan seperti streaming dan soket. Anda tidak boleh menilai dengan output pertama, Anda harus mengujinya dalam jumlah waktu tertentu.
sumber
Lihat layar ini untuk mencari kebocoran memori dengan JProfiler. Ini penjelasan visual dari Jawab Malima.
Catatan: Meskipun JProfiler bukan freeware, tetapi versi Trial dapat menangani situasi saat ini.
sumber
Karena kebanyakan dari kita sudah menggunakan Eclipse untuk menulis kode, Mengapa tidak menggunakan Memory Analyzer Tool (MAT) di Eclipse. Ini bekerja dengan baik.
The Eclipse MAT adalah satu set plug-in untuk Eclipse IDE yang menyediakan alat untuk menganalisis
heap dumps
dari aplikasi Java dan untuk mengidentifikasimemory problems
dalam aplikasi.Ini membantu pengembang untuk menemukan kebocoran memori dengan fitur-fitur berikut
sumber