Mindprod menunjukkan bahwa ini bukan pertanyaan langsung untuk dijawab:
JVM bebas untuk menyimpan data dengan cara apa pun yang diinginkan secara internal, endian besar atau kecil, dengan sejumlah padding atau overhead, meskipun primitif harus berperilaku seolah-olah mereka memiliki ukuran resmi.
Sebagai contoh, JVM atau kompiler asli mungkin memutuskan untuk menyimpan potongan boolean[]
64-bit panjang seperti a BitSet
. Tidak harus memberi tahu Anda, asalkan program memberikan jawaban yang sama.
- Ini mungkin mengalokasikan beberapa Objek sementara di stack.
- Ini dapat mengoptimalkan beberapa variabel atau pemanggilan metode yang sama sekali tidak ada dan menggantinya dengan konstanta.
- Ini mungkin versi metode atau loop, yaitu mengkompilasi dua versi metode, masing-masing dioptimalkan untuk situasi tertentu, lalu memutuskan di depan mana yang akan dipanggil.
Maka tentu saja perangkat keras dan OS memiliki cache multilayer, pada chip-cache, cache SRAM, cache DRAM, RAM yang biasa bekerja dan menyimpan cadangan di disk. Data Anda dapat digandakan di setiap level cache. Semua kompleksitas ini berarti Anda hanya dapat memperkirakan konsumsi RAM secara kasar.
Metode pengukuran
Anda bisa menggunakan Instrumentation.getObjectSize()
untuk mendapatkan perkiraan penyimpanan yang dikonsumsi oleh suatu objek.
Untuk memvisualisasikan sebenarnya tata letak objek, jejak, dan referensi, Anda dapat menggunakan JOL (Jawa Obyek Layout) alat .
Header objek dan referensi Objek
Dalam JDK 64-bit modern, sebuah objek memiliki header 12-byte, diisi hingga kelipatan 8 byte, sehingga ukuran objek minimum adalah 16 byte. Untuk JVM 32-bit, overhead adalah 8 byte, diisi hingga kelipatan 4 byte. (Dari jawaban Dmitry Spikhalskiy ini , jawaban Jayen ini , dan JavaWorld .)
Biasanya, referensi adalah 4 byte pada platform 32bit atau pada platform 64bit hingga -Xmx32G
; dan 8 byte di atas 32Gb ( -Xmx32G
). (Lihat referensi objek terkompresi .)
Akibatnya, JVM 64-bit biasanya membutuhkan 30-50% lebih banyak ruang tumpukan. ( Haruskah saya menggunakan JVM 32 atau 64-bit?, 2012, JDK 1.7)
Jenis kotak, array, dan string
Pembungkus kotak memiliki overhead dibandingkan dengan tipe primitif (dari JavaWorld ):
Integer
: Hasil 16-byte sedikit lebih buruk daripada yang saya harapkan karena int
nilai dapat masuk ke dalam hanya 4 byte tambahan. Menggunakan Integer
saya biaya overhead memori 300 persen dibandingkan ketika saya bisa menyimpan nilai sebagai tipe primitif
Long
: 16 byte juga: Jelas, ukuran objek aktual pada heap tunduk pada penyelarasan memori tingkat rendah yang dilakukan oleh implementasi JVM tertentu untuk jenis CPU tertentu. Sepertinya Long
8 byte overhead objek, ditambah 8 byte lebih untuk nilai panjang sebenarnya. Sebaliknya, Integer
memiliki lubang 4-byte yang tidak digunakan, kemungkinan besar karena JVM saya menggunakan penyelarasan objek gaya pada batas kata 8-byte.
Wadah lain juga mahal:
Array multidimensi : ia menawarkan kejutan lain.
Pengembang biasanya menggunakan konstruksi seperti int[dim1][dim2]
dalam komputasi numerik dan ilmiah.
Dalam int[dim1][dim2]
contoh array, setiap int[dim2]
array bersarang adalah Object
dalam dirinya sendiri. Masing-masing menambahkan overhead array 16-byte yang biasa. Ketika saya tidak membutuhkan array segitiga atau compang-camping, itu mewakili overhead murni. Dampaknya tumbuh ketika dimensi array sangat berbeda.
Sebagai contoh, sebuah int[128][2]
instance membutuhkan 3.600 byte. Dibandingkan dengan 1.040 byte yang int[256]
digunakan instance (yang memiliki kapasitas yang sama), 3.600 byte mewakili overhead 246 persen. Dalam kasus ekstrim byte[256][1]
, faktor overhead hampir 19! Bandingkan dengan situasi C / C ++ di mana sintaksis yang sama tidak menambahkan overhead penyimpanan.
String
: String
pertumbuhan memori a melacak pertumbuhan char array internal. Namun, String
kelas menambahkan 24 byte overhead.
Untuk nonempty String
dari ukuran 10 karakter atau kurang, biaya overhead tambahan relatif terhadap payload berguna (2 byte untuk setiap karakter ditambah 4 byte untuk panjang), berkisar 100 hingga 400 persen.
Penjajaran
Pertimbangkan contoh objek ini :
class X { // 8 bytes for reference to the class definition
int a; // 4 bytes
byte b; // 1 byte
Integer c = new Integer(); // 4 bytes for a reference
}
Jumlah yang naif akan menyarankan bahwa turunan X
akan menggunakan 17 byte. Namun, karena perataan (juga disebut padding), JVM mengalokasikan memori dalam kelipatan 8 byte, jadi alih-alih 17 byte itu akan mengalokasikan 24 byte.
Tergantung pada arsitektur / jdk. Untuk arsitektur JDK dan 64bit modern, sebuah objek memiliki header 12-byte dan padding dengan 8 byte - jadi ukuran objek minimum adalah 16 byte. Anda bisa menggunakan alat yang disebut Java Object Layout untuk menentukan ukuran dan mendapatkan detail tentang tata letak objek dan struktur internal dari setiap entitas atau menebak informasi ini dengan referensi kelas. Contoh output untuk Integer di lingkungan saya:
Jadi, untuk Integer, ukuran instance adalah 16 byte, karena 4-byte int dipadatkan tepat setelah header dan sebelum batas padding.
Contoh kode:
Jika Anda menggunakan pakar, untuk mendapatkan JOL:
sumber
Setiap objek memiliki overhead tertentu untuk monitor terkait dan mengetik informasi, serta bidang itu sendiri. Selain itu, bidang dapat ditata cukup banyak namun JVM cocok (saya percaya) - tetapi seperti yang ditunjukkan dalam jawaban lain , setidaknya beberapa JVM akan dikemas cukup ketat. Pertimbangkan kelas seperti ini:
vs.
Pada JVM 32-bit, saya berharap 100 instance
SingleByte
untuk mengambil 1200 byte (8 byte overhead + 4 byte untuk bidang karena padding / alignment). Saya berharap satu contohOneHundredBytes
untuk mengambil 108 byte - overhead, dan kemudian 100 byte, dikemas. Meskipun dapat bervariasi menurut JVM - satu implementasi mungkin memutuskan untuk tidak mengemas bidangOneHundredBytes
, sehingga membutuhkan waktu 408 byte (= 8 byte overhead + 4 * 100 byte aligned / padded byte). Pada JVM 64 bit, overhead mungkin lebih besar juga (tidak yakin).EDIT: Lihat komentar di bawah ini; rupanya HotSpot pad ke batas 8 byte, bukan 32, sehingga setiap instance
SingleByte
akan mengambil 16 byte.Apa pun itu, "objek besar tunggal" setidaknya akan seefisien beberapa objek kecil - untuk kasus sederhana seperti ini.
sumber
Total memori yang digunakan / bebas dari suatu program dapat diperoleh melalui program
Runtime memiliki beberapa metode yang berkaitan dengan memori. Contoh pengkodean berikut menunjukkan penggunaannya.
sumber
Tampaknya setiap objek memiliki overhead 16 byte pada sistem 32-bit (dan 24-byte pada sistem 64-bit).
http://algs4.cs.princeton.edu/14analysis/ adalah sumber informasi yang bagus. Salah satu contoh di antara banyak yang bagus adalah sebagai berikut.
http://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efisien-java-tutorial.pdf juga sangat informatif, misalnya:
sumber
Tidak.
sumber
Tidak, mendaftarkan objek juga membutuhkan sedikit memori. 100 objek dengan 1 atribut akan memakan lebih banyak memori.
sumber
Pertanyaannya akan sangat luas.
Itu tergantung pada variabel kelas atau Anda dapat memanggil sebagai menyatakan penggunaan memori di java.
Ini juga memiliki beberapa persyaratan memori tambahan untuk header dan referensi.
Memori tumpukan yang digunakan oleh objek Java termasuk
memori untuk bidang primitif, sesuai dengan ukurannya (lihat di bawah untuk Ukuran tipe primitif);
memori untuk bidang referensi (masing-masing 4 byte);
header objek, terdiri dari beberapa byte informasi "housekeeping";
Objek di java juga memerlukan beberapa informasi "housekeeping", seperti merekam kelas objek, ID dan bendera status seperti apakah objek saat ini dapat dijangkau, saat ini dikunci sinkronisasi dll.
Ukuran header objek Java bervariasi pada 32 dan 64 bit jvm.
Meskipun ini adalah memori utama, konsumen juga memerlukan bidang tambahan terkadang seperti untuk menyelaraskan kode, dll
Ukuran tipe primitif
boolean & byte - 1
char & short - 2
int & float - 4
panjang & ganda - 8
sumber
Saya mendapatkan hasil yang sangat baik dari pendekatan java.lang.instrument.Instrumentation yang disebutkan dalam jawaban lain. Untuk contoh penggunaannya yang baik, lihat entri, Penghitung Memori Instrumentasi dari JavaSpecialists 'Newsletter dan perpustakaan java.sizeOf di SourceForge.
sumber
Jika berguna bagi siapa pun, Anda dapat mengunduh dari agen kecil Java dari situs web saya untuk menanyakan penggunaan memori suatu objek . Ini akan membiarkan Anda meminta penggunaan memori "dalam" juga.
sumber
(String, Integer)
digunakan Cache Guava, per-elemen. Terima kasih!tidak, 100 benda kecil membutuhkan lebih banyak informasi (memori) daripada satu besar.
sumber
Aturan tentang berapa banyak memori yang dikonsumsi tergantung pada implementasi JVM dan arsitektur CPU (misalnya 32 bit versus 64 bit).
Untuk aturan terperinci untuk SUN JVM, periksa blog lama saya
Salam, Markus
sumber