GNU/Linux >> Belajar Linux >  >> Linux

Menumbuhkan penggunaan memori residen (RSS) dari Proses Java

Saya mengalami masalah yang sama. Ini adalah masalah umum dengan glibc>=2.10

Obatnya adalah dengan menyetel variabel env ini export MALLOC_ARENA_MAX=4

Artikel IBM tentang pengaturan MALLOC_ARENA_MAXhttps://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

Google untuk MALLOC_ARENA_MAX atau cari di SO untuk menemukan banyak referensi.

Anda mungkin ingin menyetel juga opsi malloc lainnya untuk mengoptimalkan fragmentasi rendah dari memori yang dialokasikan:

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536

Mungkin juga ada kebocoran memori asli. Masalah umum adalah kebocoran memori asli yang disebabkan oleh tidak menutup ZipInputStream /GZIPInputStream .

Sebuah cara umum yang menggunakan ZipInputStream dibuka adalah dengan panggilan ke Class.getResource /ClassLoader.getResource dan memanggil openConnection().getInputStream() pada java.net.URL contoh atau dengan memanggil Class.getResourceAsStream /ClassLoader.getResourceAsStream . Seseorang harus memastikan bahwa aliran ini selalu ditutup.

Beberapa pustaka sumber terbuka yang umum digunakan memiliki bug yang membocorkan java.util.zip.Inflater yang tidak tertutup atau java.util.zip.Deflater contoh. Misalnya, pustaka Nimbus Jose JWT telah memperbaiki kebocoran memori terkait di versi 6.5.1. Java JWT (jjwt) memiliki bug serupa yang diperbaiki pada versi 0.10.7. Pola bug dalam 2 kasus ini adalah fakta yang memanggil DeflaterOutputStream.close() dan InflaterInputStream.close() jangan panggil Deflater.end() /Inflater.end() ketika sebuah Deflater /Inflater contoh disediakan. Dalam kasus tersebut, tidak cukup hanya memeriksa kode untuk aliran yang ditutup. Setiap Deflater /Inflater instance yang dibuat dalam kode harus menangani .end() itu dipanggil.

Salah satu cara untuk memeriksa kebocoran Zip*Stream adalah dengan mendapatkan heap dump dan mencari instance dari kelas apa pun dengan nama "zip", "Inflater", atau "Deflater". Ini dimungkinkan di banyak alat analisis heap dump seperti Yourkit Java Profiler, JProfiler atau Eclipse MAT. Ada baiknya juga memeriksa objek dalam status finalisasi karena dalam beberapa kasus, memori dilepaskan hanya setelah finalisasi. Memeriksa kelas yang mungkin menggunakan perpustakaan asli berguna. Ini juga berlaku untuk pustaka TLS/ssl.

Ada alat OSS yang disebut pemeriksa kebocoran dari Elastic yang merupakan Agen Java yang dapat digunakan untuk menemukan sumber java.util.zip.Inflater instance yang belum ditutup (.end() tidak dipanggil).

Untuk kebocoran memori asli secara umum (tidak hanya untuk kebocoran perpustakaan zip), Anda dapat menggunakan jemalloc untuk men-debug kebocoran memori asli dengan mengaktifkan profil pengambilan sampel malloc dengan menentukan pengaturan di MALLOC_CONF variabel lingkungan. Instruksi terperinci tersedia di posting blog ini:http://www.evanjones.ca/java-native-leak-bug.html . Posting blog ini juga memiliki informasi tentang menggunakan jemalloc untuk men-debug kebocoran memori asli di aplikasi java. Ada juga postingan blog dari Elastic yang menampilkan jemalloc dan menyebutkan pemeriksa kebocoran, alat yang dibuat oleh Elastic untuk melacak masalah yang disebabkan oleh sumber daya zip inflater yang tidak ditutup.

Ada juga posting blog tentang kebocoran memori asli terkait ByteBuffers. Java 8u102 memiliki properti sistem khusus jdk.nio.maxCachedBufferSize untuk membatasi masalah cache yang dijelaskan dalam posting blog itu.

-Djdk.nio.maxCachedBufferSize=262144

Ini juga baik untuk selalu memeriksa pegangan file yang terbuka untuk melihat apakah kebocoran memori disebabkan oleh sejumlah besar file mmap:ed. Di Linux lsof dapat digunakan untuk membuat daftar file terbuka dan soket terbuka:

lsof -Pan -p PID

Laporan peta memori dari proses tersebut juga dapat membantu menyelidiki kebocoran memori asli

pmap -x PID

Untuk proses Java yang berjalan di Docker, seharusnya dimungkinkan untuk mengeksekusi perintah lsof atau pmap pada "host". Anda dapat menemukan PID dari proses kemas dengan perintah ini

docker inspect --format '{{.State.Pid}}' container_id

Ini juga berguna untuk mendapatkan thread dump (atau menggunakan jconsole/JMX) untuk memeriksa jumlah utas karena setiap utas menggunakan 1MB memori asli untuk tumpukannya. Sejumlah besar utas akan menggunakan banyak memori.

Ada juga Pelacakan Memori Asli (NMT) di JVM. Itu mungkin berguna untuk memeriksa apakah JVM itu sendiri yang menggunakan memori asli.

Alat jattach dapat digunakan juga di lingkungan kontainer (buruh pelabuhan) untuk memicu threaddump atau heapdump dari host. Itu juga dapat menjalankan perintah jcmd yang diperlukan untuk mengendalikan NMT.


Linux
  1. Ketika proses bercabang, apakah memori virtual atau residennya disalin?

  2. Penggunaan memori tinggi tetapi tidak ada proses yang menggunakannya

  3. Grafik penggunaan memori proses di Linux

  1. Cara Memeriksa Penggunaan Memori Proses dengan Perintah pmap Linux

  2. Linux – Batasi Penggunaan Memori Untuk Proses Linux Tunggal?

  3. Ubuntu Linux:Memproses memori swap dan penggunaan memori

  1. Bagaimana saya bisa mengukur penggunaan memori sebenarnya dari suatu aplikasi atau proses?

  2. Ambil penggunaan CPU dan penggunaan memori dari satu proses di Linux?

  3. Memanggil dan melacak penggunaan memori dari satu proses