Pertanyaan Mengapa ukuran maksimum tumpukan Java tetap?


Saya t aku s  tidak  mungkin untuk meningkatkan ukuran maksimum tumpukan Java setelah VM dimulai. Apa alasan teknis untuk ini? Apakah algoritma pengumpulan sampah bergantung pada jumlah memori yang tetap untuk digunakan? Atau itu untuk alasan keamanan, untuk mencegah aplikasi Java dari DOS'ing aplikasi lain pada sistem dengan mengkonsumsi semua memori yang tersedia?


32
2018-01-21 13:55


asal


Jawaban:


Di Sun's JVM, terakhir saya tahu, seluruh tumpukan harus dialokasikan dalam ruang alamat yang berdekatan. Saya membayangkan bahwa untuk nilai heap yang besar, cukup sulit untuk menambahkan ruang alamat Anda setelah startup dan memastikannya tetap berdekatan. Anda mungkin perlu mendapatkannya saat startup, atau tidak sama sekali. Jadi, sudah diperbaiki.

Bahkan jika tidak segera digunakan, ruang alamat untuk seluruh heap dicadangkan saat startup. Jika tidak dapat memesan blok alamat yang cukup besar dari ruang alamat untuk nilai -Xmx yang Anda lewati, itu akan gagal untuk memulai. Inilah sebabnya mengapa sulit untuk mengalokasikan> 1.4GB tumpukan pada Windows 32-bit - karena sulit untuk menemukan ruang alamat yang berdekatan dalam ukuran itu atau lebih besar, karena beberapa DLL suka memuat di tempat-tempat tertentu, memecah-belah ruang alamat. Ini tidak benar-benar masalah ketika Anda pergi 64-bit, karena ada begitu banyak ruang alamat.

Ini hampir pasti karena alasan kinerja. Saya tidak dapat menemukan tautan yang hebat yang merinci hal ini lebih lanjut, tetapi ini adalah kutipan yang cukup bagus dari Peter Kessler (tautan lengkap - Pastikan untuk membaca komentar) yang saya temukan ketika mencari. Saya percaya dia bekerja di JVM di Sun.

Alasannya kita membutuhkan memori yang berdekatan   wilayah untuk heap adalah bahwa kita memiliki   sekelompok struktur data samping yang   diindeks oleh offset (diskalakan) dari   mulai dari tumpukan. Misalnya, kami   melacak pembaruan referensi objek dengan   "array mark kartu" yang memiliki satu byte   untuk setiap 512 byte tumpukan. Ketika kita   menyimpan referensi di heap yang kita miliki   untuk menandai byte yang sesuai di   larik tanda kartu. Kami benar menggeser   alamat tujuan toko dan   menggunakannya untuk mengindeks array mark kartu.   Kesenangan menangani permainan aritmatika Anda   tidak dapat dilakukan di Java yang Anda dapatkan (miliki   untuk :-) bermain di C ++.

Ini pada tahun 2004 - Saya tidak yakin apa yang berubah sejak itu, tapi saya yakin itu masih berlaku. Jika Anda menggunakan alat seperti Process Explorer, Anda dapat melihat bahwa ukuran virtual (tambahkan ukuran virtual dan kolom memori ukuran pribadi) dari aplikasi Java mencakup ukuran total heap (ditambah ruang lain yang diperlukan, tidak diragukan lagi) dari titik startup , meskipun ingatan 'digunakan' oleh proses tidak akan ada di mana dekat sampai tumpukan mulai mengisi ...


23
2018-01-21 16:54



Secara historis ada alasan untuk pembatasan ini, yang tidak memungkinkan Applet di browser untuk memakan semua memori pengguna. Microsoft VM yang tidak pernah memiliki batasan seperti itu sebenarnya diizinkan untuk melakukan hal ini yang dapat menyebabkan semacam serangan Denial of Service terhadap komputer pengguna. Itu baru setahun lalu yang diperkenalkan oleh Sun di 1.6.0 Pembaruan 10 VM cara membiarkan applet menentukan berapa banyak memori yang mereka inginkan (terbatas pada bagian tetap tertentu dari memori fisik) daripada selalu membatasi mereka ke 64MB bahkan di komputer yang memiliki 8GB atau lebih tersedia.

Sekarang sejak JVM telah berevolusi seharusnya mungkin untuk menyingkirkan keterbatasan ini ketika VM tidak berjalan di dalam browser, tetapi Sun jelas tidak pernah menganggapnya sebagai masalah prioritas tinggi meskipun sudah banyak laporan bug yang diajukan untuk akhirnya. biarkan timbunan tumbuh.


8
2018-01-21 16:10



Saya pikir jawaban singkat, snarky, adalah karena Sun belum menemukannya sepadan dengan waktu dan biaya untuk berkembang.

Kasus penggunaan yang paling menarik untuk fitur semacam itu adalah pada desktop, IMO, dan Java selalu menjadi bencana di desktop ketika datang ke mekanisme peluncuran JVM. Saya menduga bahwa mereka yang berpikir paling tentang isu-isu tersebut cenderung fokus pada sisi server dan melihat detail lain yang paling baik diserahkan kepada pembungkus asli. Ini adalah keputusan yang tidak menguntungkan, tetapi seharusnya hanya menjadi salah satu poin keputusan ketika memutuskan pada platform yang tepat untuk sebuah aplikasi.


4
2018-01-21 14:12



Firasat saya adalah bahwa hal itu ada hubungannya dengan manajemen memori sehubungan dengan aplikasi lain yang berjalan pada sistem operasi.

Jika Anda mengatur ukuran heap maksimum ke, misalnya, jumlah RAM pada kotak Anda secara efektif membiarkan VM memutuskan berapa banyak memori yang diperlukan (hingga batas ini). Masalah dengan ini adalah bahwa VM dapat secara efektif melumpuhkan mesin yang sedang berjalan karena akan mengambil alih semua memori pada kotak sebelum memutuskan bahwa itu perlu mengumpulkan sampah.

Ketika Anda menentukan ukuran tumpukan maksimal, apa yang Anda katakan kepada VM, Anda diizinkan untuk menggunakan jumlah memori ini sebelum Anda perlu mulai mengumpulkan sampah. Anda tidak dapat memiliki lebih banyak karena jika Anda mengambil lebih banyak maka aplikasi lain yang berjalan pada kotak akan melambat dan Anda akan mulai menukar ke disk jika Anda menggunakan lebih dari ini.

Juga perhatikan bahwa mereka adalah dua nilai berkenaan dengan memori, yaitu "ukuran tumpukan saat ini" dan "ukuran tumpukan maksimal". Ukuran heap saat ini adalah seberapa banyak ukuran memori yang digunakan saat ini dan, jika membutuhkan lebih banyak, ukurannya dapat diubah menjadi tumpukan tetapi tidak dapat mengubah ukuran tumpukan di atas nilai ukuran tumpukan maksimum.


3
2018-01-21 14:16



Dari IBM kiat tuning kinerja (jadi mungkin tidak langsung berlaku untuk VM Sun)

Parameter tumpukan Java mempengaruhi perilaku pengumpulan sampah. Meningkatkan ukuran heap mendukung lebih banyak pembuatan objek. Karena tumpukan besar membutuhkan waktu lebih lama untuk mengisi, aplikasi berjalan lebih lama sebelum pengumpulan sampah terjadi. Namun, tumpukan yang lebih besar juga membutuhkan waktu lebih lama untuk memadat dan menyebabkan pengumpulan sampah menjadi lebih lama.

JVM memiliki ambang batas yang digunakan untuk mengelola penyimpanan JVM. Ketika ambang tercapai, pengumpul sampah dipanggil untuk membebaskan ruang penyimpanan yang tidak digunakan. Oleh karena itu, pengumpulan sampah dapat menyebabkan degradasi yang signifikan dari kinerja Jawa. Sebelum mengubah ukuran tumpukan awal dan maksimum, Anda harus mempertimbangkan informasi berikut:   Dalam sebagian besar kasus, Anda harus menetapkan ukuran tumpukan JVM maksimum ke nilai lebih tinggi dari ukuran tumpukan JVM awal. Hal ini memungkinkan JVM untuk beroperasi secara efisien selama normal, periode steady state dalam batas-batas tumpukan awal tetapi juga untuk beroperasi secara efektif selama periode volume transaksi tinggi dengan memperluas tumpukan hingga ukuran tumpukan JVM maksimum. Dalam beberapa kasus langka di mana kinerja optimal mutlak diperlukan Anda mungkin ingin menentukan nilai yang sama untuk ukuran tumpukan awal dan maksimum. Ini akan menghilangkan beberapa overhead yang terjadi ketika JVM perlu memperluas atau mengontrak ukuran tumpukan JVM. Pastikan wilayahnya cukup besar untuk menampung tumpukan JVM yang ditentukan.   Waspadai membuat Ukuran Heap Awal terlalu besar. Meskipun ukuran tumpukan yang besar pada awalnya meningkatkan kinerja dengan menunda pengumpulan sampah, namun ukuran tumpukan yang besar pada akhirnya memengaruhi waktu respons ketika pengumpulan sampah akhirnya dimulai karena proses pengumpulan membutuhkan waktu lebih lama.

Jadi, saya kira alasan mengapa Anda tidak dapat mengubah nilai pada saat runtime adalah karena mungkin tidak membantu: apakah Anda memiliki cukup ruang di heap Anda atau tidak. Setelah Anda kehabisan, siklus GC akan dipicu. Jika itu tidak mengosongkan ruang, Anda tetap diisi. Anda harus menangkap OutOfMemoryException, meningkatkan ukuran heap, dan kemudian mencoba lagi perhitungan, berharap kali ini Anda memiliki cukup memori.

Secara umum VM tidak akan menggunakan ukuran heap maksimum kecuali Anda membutuhkannya, jadi jika Anda berpikir Anda mungkin perlu memperluas memori pada saat runtime, Anda bisa menentukan ukuran tumpukan maksimum yang besar.

Saya akui itu semua agak tidak memuaskan, dan tampaknya agak malas, karena saya bisa membayangkan strategi pengumpulan sampah yang masuk akal yang akan meningkatkan ukuran tumpukan ketika GC gagal untuk membebaskan ruang yang cukup. Apakah imajinasi saya diterjemahkan menjadi implementasi GC kinerja tinggi adalah masalah lain;)


2
2018-01-21 14:42