Kích thước của một biến boolean trong Java là gì?


89

Có ai có thể cho biết kích thước bit của boolean trong Java không?


1
Điều tương tự cũng được hỏi ở đây: stackoverflow.com/questions/1907318/…
dma_k Ngày

Câu trả lời:


41

Nó phụ thuộc vào máy ảo.


9
Bạn quan tâm đến một số tài liệu? Tôi thấy khó tin rằng kích thước của boolean phụ thuộc vào máy móc. Điều đó có nghĩa là biểu diễn nhị phân của một lớp chứa boolean sẽ có các kích thước khác nhau (và bố cục bộ nhớ) trong các máy ảo khác nhau và điều đó có nghĩa là các máy ảo sẽ không tương thích.
David Rodríguez - dribeas

14
Tôi nghĩ rằng câu hỏi đề cập đến kích thước của một biến boolean trong bộ nhớ, không phải kích thước của một biến boolean được mã hóa trong một tệp lớp. Kích thước trong bộ nhớ khác nhau tùy theo máy ảo theo tài liệu của Sun. Kích thước trong tệp lớp là không đổi.
William Brendel

3
@ DavidRodríguez-dribeas - The Sun JVM vào khoảng thời gian của Java 1.1 đã sử dụng 4 byte cho boolean khi được lưu trữ dưới dạng instance hoặc auto var. Điều này đã đơn giản hóa việc triển khai trình thông dịch bytecode (liên quan đến các bools chiếm 4 byte trên ngăn xếp) và là con đường ít kháng cự nhất. Khi chúng tôi triển khai iSeries "Classic" JVM, chúng tôi đã tìm ra cách để tạo các vars phiên bản 1 byte, vì điều đó đã cải thiện đáng kể độ nhỏ gọn của một số đối tượng (có tác động đáng kinh ngạc đến hiệu suất). Rõ ràng, dựa trên các bài đăng dưới đây, các nhà phát triển Sun / Oracle đã tìm ra cách làm tương tự trong các phiên bản sau.
Hot Licks,

Nhưng đó là đúng, tính đến cuối năm 2017 JavaDocs nói: boolean: The boolean data type... This data type represents one bit of information, but its "size" isn't something that's precisely defined- nhưng quan điểm của bạn là hợp lệ, nó có thể sử dụng một số liên kết và thông tin tốt hơn :)
JimLohse

185

Nó phụ thuộc vào máy ảo, nhưng thật dễ dàng để điều chỉnh mã từ một câu hỏi tương tự hỏi về byte trong 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();
    }
}

Để nhắc lại, điều này phụ thuộc vào máy ảo, nhưng trên máy tính xách tay Windows của tôi chạy phiên bản JDK của Sun 1.6.0_11, tôi nhận được kết quả sau:

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

Điều đó cho thấy rằng boolean về cơ bản có thể được đóng gói thành một byte mỗi bởi JVM của Sun.


21
@skeet - Tôi thực sự chào bạn. câu trả lời của bạn thật tuyệt vời
Warrior

2
@warrior: Vì tôi đã có mã cho "byte" rồi, nên việc thay đổi nó thành "boolean" khá đơn giản :)
Jon Skeet

3
System.gc () không đảm bảo dọn dẹp bộ nhớ. Nó chỉ ra lệnh cho JVM chạy bộ thu gom rác, nhưng nó không có nghĩa là bộ thu gom thực sự đã làm sạch thứ gì đó. Hãy nhớ bộ sưu tập dọn dẹp các đối tượng UNUSED. Một đối tượng không được sử dụng nếu chương trình không còn tham chiếu đến nó. Vì vậy, trong thử nghiệm của bạn, tôi sẽ loại bỏ tham chiếu một cách rõ ràng bằng cách đặt LotsOfBooleans thành null trước khi chạy gc (); HOẶC chỉ chạy main một lần với boolean, một lần với int rồi so sánh các số.
Randa Sbeity

2
@RandaSbeity Hoặc thậm chí tốt hơn: đảm bảo bạn bảo toàn cả hai tham chiếu và tính toán chênh lệch bộ nhớ. Đó chính xác là những gì xảy ra ở đây.
biziclop

1
Có câu hỏi nào mà Jon Skeet không thể trả lời?
Andreas Hartmann

31

Thông tin thực tế được biểu diễn bằng giá trị boolean trong Java là một bit: 1 cho true, 0 cho false. Tuy nhiên, kích thước thực của một biến boolean trong bộ nhớ không được đặc tả Java xác định chính xác. Xem Các kiểu dữ liệu nguyên thủy trong Java .

Kiểu dữ liệu boolean chỉ có hai giá trị có thể có: true và false. Sử dụng kiểu dữ liệu này cho các cờ đơn giản theo dõi các điều kiện đúng / sai. Kiểu dữ liệu này đại diện cho một bit thông tin, nhưng "kích thước" của nó không phải là thứ được xác định chính xác.


21

Còn một chú ý đáng nói...

Nếu bạn đang nghĩ đến việc sử dụng một mảng các đối tượng Boolean, thì đừng. Thay vào đó, hãy sử dụng BitSet - nó có một số tối ưu hóa hiệu suất (và một số phương pháp bổ sung hay, cho phép bạn lấy bit đặt / hủy đặt tiếp theo).


Điều này không phải lúc nào cũng đúng stackoverflow.com/questions/605226/…
Przemek

Câu trả lời đó cho thấy có những lý do quan trọng để sử dụng boolean [], nhưng như các nhận xét ở đó chỉ ra, không có nhiều điều để sao lưu. Có nói rằng: Tôi không chương trình nhiều trong Java (và không cung cấp bất kỳ bằng chứng hoặc;)
Matthew Schinckel

6

Tôi đọc rằng Java dự trữ một byte cho một booleankiểu dữ liệu, nhưng nó chỉ sử dụng một bit. Tuy nhiên, tài liệu nói rằng "kích thước" của nó "không phải là thứ được xác định chính xác" . Xem tại đây.


Đó là một hướng dẫn, không phải 'tài liệu'. Tài liệu là JLS, JVM Spec. Và Javadoc.
Marquis of Lorne

2

Các booleangiá trị được biên dịch thành intkiểu dữ liệu trong JVM. Xem tại đây .


2
Đó không nhất thiết là cách chúng được lưu trữ trong bộ nhớ, và tôi nghĩ đó là điều mà người đặt câu hỏi muốn biết. Tài liệu đó mô tả định dạng tệp lớp (mã byte đã biên dịch), không phải là biểu diễn của một biến boolean trong bộ nhớ, vì điều đó phụ thuộc vào việc triển khai.
William Brendel

2

Kích thước của boolean trong java phụ thuộc vào máy ảo. nhưng Bất kỳ đối tượng Java nào đều được căn chỉnh để có độ chi tiết 8 byte. Một Boolean có 8 byte tiêu đề, cộng với 1 byte trọng tải, cho tổng số 9 byte thông tin. JVM sau đó làm tròn nó lên bội số tiếp theo của 8. do đó, một phiên bản java.lang.Boolean chiếm 16 byte bộ nhớ.


Tôi sẽ có xu hướng không đồng ý, trên HotSpot JVM 1.7.0_51, tiêu đề có 12 byte + 1 cho boolean + 3 cho mức độ chi tiết.
Eugene,

14
đừng nhầm lẫn Boolean với boolean.
andresp

1
Byte hay bit? 16 Bytes cho một Booleanwold được một sự lãng phí như vậy ... đó là kích thước của một longmà có thể mang nhiều nghìn tỷ lần thông tin hơn mộtBoolean
Dici

0

Nó không xác định; làm những điều như Jon Skeet đề xuất sẽ giúp bạn có được giá trị gần đúng trên một nền tảng nhất định, nhưng cách để biết chính xác cho một nền tảng cụ thể là sử dụng một trình mô tả.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.