Berapa ukuran variabel boolean di Java?

89

Bisakah seseorang mengetahui ukuran bit boolean di Java?

DonX
sumber
1
Hal yang sama ditanyakan di sini: stackoverflow.com/questions/1907318/…
dma_k

Jawaban:

41

Ini bergantung pada mesin virtual.

pejuang
sumber
9
Mau menunjuk ke beberapa dokumen? Saya merasa sulit untuk percaya bahwa ukuran boolean bergantung pada mesin. Itu berarti bahwa representasi biner dari sebuah kelas yang berisi boolean akan memiliki ukuran (dan tata letak memori) yang berbeda di VM yang berbeda dan itu akan menyiratkan bahwa VM tidak akan kompatibel.
David Rodríguez - dribeas
14
Saya pikir itu tersirat bahwa pertanyaannya mengacu pada ukuran variabel boolean dalam memori, bukan ukuran variabel boolean yang dikodekan dalam file kelas. Ukuran dalam memori bervariasi menurut VM menurut dokumentasi Sun. Ukuran file kelas konstan.
William Brendel
3
@ DavidRodríguez-dribeas - Sun JVM sekitar waktu Java 1.1 menggunakan 4 byte untuk boolean saat disimpan sebagai instance atau var otomatis. Ini menyederhanakan implementasi interpreter bytecode (yang menganggap bools menempati 4 byte di stack) dan merupakan jalur dengan resistansi paling kecil. Ketika kami mengimplementasikan iSeries "Classic" JVM, kami menemukan cara untuk membuat instance vars 1 byte, karena hal itu sangat meningkatkan kekompakan beberapa objek (yang berdampak luar biasa pada kinerja). Rupanya, berdasarkan posting di bawah ini, pengembang Sun / Oracle menemukan cara melakukan hal yang sama di versi yang lebih baru.
Hot Licks
Tapi itu benar, pada akhir 2017 JavaDocs mengatakan: boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined- tetapi maksud Anda valid, itu bisa menggunakan beberapa tautan dan info yang lebih baik :)
JimLohse
185

Itu tergantung pada mesin virtual, tetapi mudah untuk menyesuaikan kode dari pertanyaan serupa yang menanyakan tentang byte di Java :

class LotsOfBooleans
{
    boolean a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    boolean b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    boolean c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    boolean d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    boolean e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}

class LotsOfInts
{
    int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af;
    int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf;
    int c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf;
    int d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df;
    int e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef;
}


public class Test
{
    private static final int SIZE = 1000000;

    public static void main(String[] args) throws Exception
    {        
        LotsOfBooleans[] first = new LotsOfBooleans[SIZE];
        LotsOfInts[] second = new LotsOfInts[SIZE];

        System.gc();
        long startMem = getMemory();

        for (int i=0; i < SIZE; i++)
        {
            first[i] = new LotsOfBooleans();
        }

        System.gc();
        long endMem = getMemory();

        System.out.println ("Size for LotsOfBooleans: " + (endMem-startMem));
        System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));

        System.gc();
        startMem = getMemory();
        for (int i=0; i < SIZE; i++)
        {
            second[i] = new LotsOfInts();
        }
        System.gc();
        endMem = getMemory();

        System.out.println ("Size for LotsOfInts: " + (endMem-startMem));
        System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE)));

        // Make sure nothing gets collected
        long total = 0;
        for (int i=0; i < SIZE; i++)
        {
            total += (first[i].a0 ? 1 : 0) + second[i].a0;
        }
        System.out.println(total);
    }

    private static long getMemory()
    {
        Runtime runtime = Runtime.getRuntime();
        return runtime.totalMemory() - runtime.freeMemory();
    }
}

Untuk mengulangi, ini bergantung pada VM, tetapi pada laptop Windows saya yang menjalankan JDK build 1.6.0_11 Sun, saya mendapatkan hasil sebagai berikut:

Size for LotsOfBooleans: 87978576
Average size: 87.978576
Size for LotsOfInts: 328000000
Average size: 328.0

Itu menunjukkan bahwa boolean pada dasarnya dapat dikemas menjadi satu byte masing-masing oleh JVM Sun.

Jon Skeet
sumber
21
@skeet - Saya sangat menghormati Anda. jawaban Anda luar biasa
Warrior
2
@warrior: Karena saya sudah mendapatkan kode untuk "byte", mengubahnya menjadi "boolean" sangatlah mudah :)
Jon Skeet
3
System.gc () tidak menjamin pembersihan memori. Ini hanya memberi perintah kepada JVM untuk menjalankan pengumpulan sampah, tetapi itu tidak berarti bahwa kolektor benar-benar membersihkan sesuatu. Ingat kolektor membersihkan benda-benda yang TIDAK DIGUNAKAN. Sebuah objek tidak digunakan jika program tidak menyimpan referensi lagi padanya. Jadi dalam pengujian Anda, saya akan secara eksplisit menjatuhkan referensi dengan menyetel LotsOfBooleans ke null sebelum menjalankan gc (); ATAU jalankan main sekali dengan boolean, sekali dengan int lalu bandingkan angkanya.
Randa Sbeity
2
@RandaSbeity Atau bahkan lebih baik: pastikan Anda menyimpan kedua referensi dan menghitung perbedaan memori. Itulah yang sebenarnya terjadi di sini.
biziclop
1
Apakah ada pertanyaan yang tidak bisa dijawab Jon Skeet?
Andreas Hartmann
31

Informasi aktual yang diwakili oleh nilai boolean di Java adalah satu bit: 1 untuk benar, 0 untuk salah. Namun, ukuran sebenarnya dari variabel boolean dalam memori tidak ditentukan secara tepat oleh spesifikasi Java. Lihat Tipe Data Primitif di Java .

Tipe data boolean hanya memiliki dua kemungkinan nilai: benar dan salah. Gunakan tipe data ini untuk tanda sederhana yang melacak kondisi benar / salah. Tipe data ini mewakili satu bit informasi, tetapi "ukurannya" bukanlah sesuatu yang didefinisikan dengan tepat.

William Brendel
sumber
21

Di samping catatan ...

Jika Anda berpikir tentang menggunakan larik objek Boolean, jangan. Gunakan BitSet sebagai gantinya - ini memiliki beberapa optimisasi kinerja (dan beberapa metode tambahan yang bagus, memungkinkan Anda untuk mendapatkan bit set / unset berikutnya).

Matthew Schinckel
sumber
Ini tidak selalu benar stackoverflow.com/questions/605226/…
Przemek
Jawaban tersebut menunjukkan bahwa ada alasan yang signifikan untuk menggunakan boolean [], tetapi seperti yang ditunjukkan oleh komentar di sana, tidak banyak yang mendukungnya. Karena itu: Saya tidak banyak memprogram di Java (dan juga tidak memberikan bukti apa pun;)
Matthew Schinckel
6

Saya membaca bahwa Java mencadangkan satu byte untuk booleantipe data, tetapi hanya menggunakan satu bit. Namun, dokumentasi mengatakan bahwa "ukurannya" bukanlah sesuatu yang didefinisikan dengan tepat " . Lihat disini.

JavaNewbie_M107
sumber
Itu tutorial, bukan 'dokumentasi'. Dokumentasinya adalah JLS, JVM Spec., Dan Javadoc.
Marquis dari Lorne
2

The booleannilai-nilai yang dikompilasi untuk inttipe data di JVM. Lihat disini .

rics
sumber
2
Itu belum tentu bagaimana mereka disimpan dalam memori, dan saya pikir itulah yang ingin diketahui oleh orang yang mengajukan pertanyaan. Dokumen tersebut menjelaskan format file kelas (kode byte terkompilasi), bukan representasi variabel boolean dalam memori, karena itu bergantung pada implementasi.
William Brendel
2

Ukuran boolean di java bergantung pada mesin virtual. tetapi Objek Java apa pun disejajarkan dengan perincian 8 byte. Sebuah Boolean memiliki 8 byte header, ditambah 1 byte payload, dengan total 9 byte informasi. JVM kemudian membulatkannya ke kelipatan 8. sehingga satu instance java.lang.Boolean membutuhkan 16 byte memori.

Deepak Odedara
sumber
Saya akan cenderung tidak setuju, pada HotSpot JVM 1.7.0_51 header memiliki 12 byte + 1 untuk boolean + 3 untuk perincian.
Eugene
14
jangan bingung antara Boolean dengan boolean.
danresp
1
Byte atau bit? 16 Bytes Booleansungguh sia-sia ... itu ukuran longyang dapat membawa informasi triliun kali lebih banyak daripadaBoolean
Dici
0

Ini tidak ditentukan; melakukan hal-hal seperti yang disarankan Jon Skeet akan memberi Anda perkiraan pada platform tertentu, tetapi cara untuk mengetahui secara tepat untuk platform tertentu adalah dengan menggunakan profiler.

Lawrence Dol
sumber