1. Batas atas alokasi array
Ukuran array di Java terbatas karena menggunakan tipe int sebagai subskrip array. Ini berarti Anda tidak dapat mengajukan array yang melebihi ukuran integer.max_value (2^31-1). Ini tidak berarti bahwa batas atas aplikasi memori Anda adalah 2G. Anda dapat melamar berbagai jenis yang lebih besar. Misalnya:
Salinan kode adalah sebagai berikut:
final long [] ar = new Long [integer.max_value];
Ini akan mengalokasikan 16g -8 byte. hanyalah aturan umum, alokasi spesifik tergantung pada situasi aktual).
Sayangnya, di Java, karena keterbatasan jenis elemen array, akan lebih merepotkan untuk mengoperasikan memori. Ketika datang ke array operasi, BytEbuffer harus menjadi kelas yang paling berguna, yang menyediakan metode untuk membaca dan menulis jenis Java yang berbeda. Kerugiannya adalah bahwa tipe array target harus byte [], yang berarti bahwa cache memori maksimum yang Anda alokasikan dapat 2g.
2. Gunakan semua array sebagai array byte untuk beroperasi
Dengan asumsi bahwa memori 2G jauh dari cukup bagi kita sekarang, tidak apa -apa jika 16g. Kami telah menugaskan [] yang panjang, tetapi kami ingin mengoperasikannya sebagai array byte. Di Java kami harus meminta bantuan dari programmer C - Sun.misc.unsafe. Kelas ini memiliki dua set metode: getn (objek, offset), metode ini adalah untuk mendapatkan nilai dari jenis yang ditentukan dari posisi di mana objek offset diimbangi dan mengembalikannya Metode putn (objek, offset, value) adalah menulis nilai ke posisi offset objek.
Sayangnya, metode ini hanya bisa mendapatkan atau mengatur nilai dari jenis tertentu. Jika Anda menyalin data dari array, Anda juga memerlukan metode lain yang tidak aman, copymemory (SRCObject, Srcoffset, DestObject, Destoffet, Count). Ini berfungsi mirip dengan System.arraycopy, tetapi menyalin byte daripada elemen array.
Untuk mengakses data array melalui sun.misc.unsafe, Anda membutuhkan dua hal:
1. Offset data di objek array
2. Offset elemen yang disalin dalam data array
Seperti objek Java lainnya, array memiliki header objek, yang disimpan di depan data aktual. Panjang header ini dapat diperoleh dengan metode yang tidak aman.arraybaseoffset (t []. Ukuran elemen array dapat diperoleh melalui metode yang tidak aman. Ini berarti bahwa jika Anda ingin mengakses elemen ke -n tipe t, offset offset Anda harus arrayoffset+n*arrayscale.
Mari kita tulis contoh sederhana. Kami mengalokasikan array yang panjang dan memperbarui beberapa byte di dalamnya. Kami memperbarui elemen terakhir ke -1 (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFff
Salinan kode adalah sebagai berikut:
final long [] ar = new Long [1000];
indeks int akhir = ar.length - 1;
ar [index] = -1; // fffffffffff
System.out.println ("Sebelum ubah =" + long.tohexstring (ar [index]));
untuk (panjang i = 0; i <8; ++ i)
{
uncafe.putbyte (AR, longArrayOffset + 8l * index + i, (byte) 0);
System.out.println ("After Change: i =" + i + ", val =" + long.tohexstring (ar [index]));
}
Jika Anda ingin menjalankan contoh di atas, Anda harus menambahkan blok kode statis berikut ke kelas tes Anda:
Salinan kode adalah sebagai berikut:
final privat statis tidak aman;
statis
{
mencoba
{
Bidang bidang = uncafe.class.getDeclaredfield ("theunsafe");
field.setAccessible (true);
tidak aman = (tidak aman) field.get (null);
}
Tangkap (pengecualian e)
{
Lempar RuntimeException baru (E);
}
}
final private static longarrayoffset = uncafe.arraybaseoffset (long []. class);
Hasil outputnya adalah:
Salinan kode adalah sebagai berikut:
Sebelum ubah = ffffffffffffffffff
After Change: i = 0, val = ffffffffffffff00
After Change: i = 1, val = ffffffffffff0000
After Change: i = 2, val = fffffffffff000000
After Change: i = 3, val = fffffffff00000000
After Change: i = 4, Val = FFFFFF00000000000
After Change: i = 5, Val = FFFF0000000000000
After Change: i = 6, val = ff000000000000000
Setelah perubahan: i = 7, val = 0
3. Alokasi Memori Sun.Misc.unsafe
Seperti disebutkan di atas, dalam Java murni, ukuran memori yang dapat kita alokasikan terbatas. Pembatasan ini diatur dalam versi awal Java, dan pada saat itu orang tidak berani berbagi beberapa g memori seperti ini. Tapi sekarang ini adalah era Big Data, dan kami membutuhkan lebih banyak memori. Di Java, ada dua cara untuk mendapatkan lebih banyak memori:
1. Alokasikan banyak potongan kecil memori dan kemudian secara logis menggunakannya sebagai bagian besar yang terus menerus.
2. Gunakan sun.misc.unsafe.allcatememory (Long) untuk mengalokasikan memori.
Metode pertama hanya sedikit lebih menarik dari perspektif algoritma, jadi mari kita lihat metode kedua.
sun.misc.unsafe menyediakan serangkaian metode untuk mengalokasikan, mengalokasikan kembali, dan melepaskan memori. Mereka sangat mirip dengan metode Malloc/gratis C:
1.Bong tidak aman.Allocatememory (Ukuran Panjang) -Salokal Ruang Memori. Sepotong memori ini mungkin berisi data sampah (tidak secara otomatis dihapus). Jika alokasi gagal, pengecualian java.lang.outofmemoryError akan dilemparkan. Ini mengembalikan alamat memori yang tidak nol (lihat deskripsi di bawah).
2.unsafe.reallocatememory (alamat panjang, ukuran panjang)-Beri kembali sepotong memori dan salin data dari buffer memori lama (di mana alamat menunjuk ke) blok memori yang baru dialokasikan. Jika alamatnya sama dengan 0, metode ini memiliki efek yang sama dengan alocatememory. Ini mengembalikan alamat buffer memori baru.
3.unsafe.freememory (Alamat Panjang) -Reburan Buffer memori yang dihasilkan oleh dua metode sebelumnya. Jika alamatnya 0, tidak melakukan apa -apa.
Memori yang dialokasikan oleh metode ini harus digunakan dalam mode yang disebut alamat register tunggal: Tidak aman menyediakan serangkaian metode yang hanya menerima satu parameter alamat (tidak seperti mode register ganda, mereka memerlukan objek dan offset offset). Memori yang dialokasikan dengan cara ini bisa lebih besar dari apa yang Anda konfigurasi dalam parameter Java -xmx.
Catatan: Memori yang dialokasikan oleh tidak aman tidak dapat dikumpulkan sampah. Anda harus memperlakukannya sebagai sumber daya normal dan mengelolanya sendiri.
Berikut adalah contoh penggunaan yang tidak aman. Allocatememory untuk mengalokasikan memori, dan juga memeriksa apakah seluruh buffer memori dapat dibaca dan dapat ditulis:
Salinan kode adalah sebagai berikut:
Ukuran int akhir = integer.max_value / 2;
final long addr = uncafe.allocatememory (size);
mencoba
{
System.out.println ("Alamat Tidak Aman =" + Addr);
untuk (int i = 0; i <size; ++ i)
{
uncafe.putbyte (addr + i, (byte) 123);
if (uncafe.getbyte (addr + i)! = 123)
System.out.println ("Gagal di Offset =" + i);
}
}
Akhirnya
{
uncafe.freememory (addr);
}
Seperti yang Anda lihat, menggunakan sun.misc.unsafe Anda dapat menulis kode akses memori yang sangat umum: tidak peduli jenis memori apa yang dialokasikan di java, Anda dapat membaca dan menulis semua jenis data sesuka hati.