2009-12-15 39 views
102

Số Java Virtual Machine Specification cho biết rằng có sự hỗ trợ giới hạn đối với các loại nguyên thủy boolean.Tại sao kích thước nguyên thủy boolean của Java không được xác định?

Không có hướng dẫn máy ảo Java nào chỉ dành riêng cho các thao tác trên giá trị boolean. Thay vào đó, các biểu thức trong ngôn ngữ lập trình Java hoạt động trên các giá trị boolean được biên dịch để sử dụng các giá trị của kiểu dữ liệu int máy ảo Java.

Hàm trên có nghĩa là (mặc dù tôi có thể hiểu sai) rằng kiểu dữ liệu int được sử dụng khi hoạt động trên boolean, nhưng đây là cấu trúc bộ nhớ 32 bit. Giả sử boolean chỉ đại diện cho 1 bit thông tin:

  • Tại sao byte, hoặc loại ngắn không được sử dụng làm proxy cho boolean thay vì int?
  • Đối với bất kỳ JVM nhất định nào là cách đáng tin cậy nhất để tìm ra chính xác số lượng bộ nhớ được sử dụng để lưu trữ một loại boolean?

Trả lời

105

Câu trả lời ngắn gọn: có, giá trị boolean được xử lý dưới dạng thực thể 32 bit, nhưng mảng các boolean sử dụng 1 byte cho mỗi phần tử.

Câu trả lời dài hơn: JVM sử dụng ô ngăn xếp 32 bit, được sử dụng để giữ các biến cục bộ, đối số phương thức và giá trị biểu thức. Các nguyên thủy nhỏ hơn 1 ô được đệm ra, các nguyên thủy lớn hơn 32 bit (dài và đôi) lấy 2 ô. Kỹ thuật này giảm thiểu số lượng opcodes, nhưng có một số tác dụng phụ đặc biệt (chẳng hạn như nhu cầu mặt nạ byte).

Các thành phần được lưu trữ trong mảng có thể sử dụng dưới 32 bit và có các mã opcodes khác nhau để tải và lưu trữ các giá trị nguyên thủy từ một mảng. Các giá trị Boolean và byte đều sử dụng các mã opcode và bastore, ngụ ý rằng các mảng boolean lấy 1 byte cho mỗi phần tử.

Theo cách bố trí đối tượng trong bộ nhớ, điều này được bao phủ trong "triển khai riêng" rules, có thể là 1 bit, 1 byte hoặc như một áp phích khác được ghi chú, liên kết với ranh giới hai byte 64 bit . Nhiều khả năng, nó có kích thước từ cơ bản của phần cứng cơ bản (32 hoặc 64 bit).


Theo như giảm thiểu lượng không gian mà booleans sử dụng: nó thực sự không phải là vấn đề đối với hầu hết các ứng dụng. Các khung ngăn xếp (giữ các biến cục bộ và đối số phương thức) không phải là rất lớn, và trong lược đồ lớn, một boolean rời rạc trong một đối tượng cũng không lớn. Nếu bạn có rất nhiều đối tượng với nhiều boolean, thì bạn có thể sử dụng các trường bit được quản lý thông qua getters và setters của bạn. Tuy nhiên, bạn sẽ phải trả một khoản phạt trong thời gian CPU mà có lẽ lớn hơn hình phạt trong bộ nhớ.

+0

Bạn có chắc chắn về 1 bit trong một mảng boolean không? –

+3

Tôi tin rằng tôi đã viết "byte". Đó chắc chắn là "byte" ngay bây giờ, mặc dù có thể là bản chỉnh sửa trước đó của tôi đã sử dụng "bit". – kdgregory

+0

Đối với các thành viên lớp boolean/byte, nó cũng đúng, rằng chúng cũng là 4 byte? Ví dụ lớp được phân bổ như một toàn bộ trên ngăn xếp, vì vậy tôi có thể tưởng tượng, JVM có lẽ nên sử dụng 1 byte cho mỗi thành viên boolean/byte và cuối cùng tạo một liên kết 4 byte cho cá thể lớp hoàn chỉnh. Có phải vậy không?(nếu bạn có tài liệu tham khảo chứng minh điều này, xin vui lòng, chia sẻ) –

3

Lập bản đồ boolean được thực hiện với CPU 32 bit trong đầu. Giá trị int có 32 bit để nó có thể được xử lý trong một thao tác.

Dưới đây là một giải pháp từ Peter Norvig's Java IAQ: Infrequently Answered Questions để đo kích thước (với một số không chính xác):

static Runtime runtime = Runtime.getRuntime(); 
... 
long start, end; 
Object obj; 
runtime.gc(); 
start = runtime.freememory(); 
obj = new Object(); // Or whatever you want to look at 
end = runtime.freememory(); 
System.out.println("That took " + (start-end) + " bytes."); 
+0

Vì cuộc hội thoại này là về nguyên thủy, bạn phải sáng tạo trong việc kiểm tra điều này vì nguyên thủy không được lưu trữ trong heap trừ khi chúng là một trường trên một thể hiện hoặc một mảng. Và không ai trả lời câu hỏi về cách Java sẽ chọn lưu trữ nó trong ngăn xếp. – Jesse

7

Một boolean đơn ở đâu đó trong hệ thống phân cấp thừa kế có thể sử dụng lên đến 8 byte! Điều này là do padding. Thông tin chi tiết có thể được tìm thấy trong How much memory is used by my Java object?:

Trở lại các câu hỏi về cách nhiều một tiêu thụ boolean, vâng nó tiêu thụ ít nhất một byte, nhưng do alignment cai trị nó có thể tiêu thụ nhiều hơn. IMHO thú vị hơn là biết rằng boolean [] sẽ tiêu thụ một byte mỗi lần nhập và không phải một bit, cộng với một số chi phí do căn chỉnh và cho trường kích thước của mảng. Có thuật toán đồ thị trong đó các trường lớn là bit rất hữu ích và bạn cần phải là nhận thức được rằng, nếu bạn sử dụng boolean [] bạn cần gần gấp 8 lần bộ nhớ hơn mức cần thiết (1 byte so với 1 bit).

+0

Làm thế nào để sử dụng boolean []? –

+0

boolean [] có thể được sử dụng cho mặt nạ. Đôi khi một BitSet có thể tốt hơn, bởi vì nó có một số phương pháp hữu ích. –

1

CPU hoạt động trên độ dài datatype cụ thể. Trong trường hợp CPU 32 bit, chúng dài 32 bit và do đó bạn gọi 'int' trong Java. Mọi thứ bên dưới hoặc bên trên phải được lấp đầy hoặc chia nhỏ với độ dài này trước khi CPU có thể xử lý nó. Điều này không mất nhiều thời gian, nhưng nếu bạn cần 2 chu kỳ CPU thay vì 1 cho các hoạt động cơ bản, điều này có nghĩa là chi phí gấp đôi/lần.

Thông số này dành riêng cho CPU 32 bit để chúng có thể xử lý các boolean với kiểu dữ liệu gốc của chúng.

Bạn chỉ có thể có ở đây: tốc độ hoặc bộ nhớ - SUN đã quyết định về tốc độ.

-10

Tại sao không làm một file java như thế này:

Empty.java

class Empty{ 
} 

và một lớp như thế này:

NotEmpty.java

class NotEmpty{ 
    boolean b; 
} 

Compile họ cả hai và so sánh các tệp .class với trình chỉnh sửa hex.

+4

đây là một chỉ số khác hoàn toàn, không liên quan đến việc định kích thước kiểu boolean nguyên thủy trong bộ nhớ. – Joel

5

Ấn bản thứ năm của Java trong Nutshell (O'Reilly) cho biết loại nguyên thủy boolean là 1 byte. Điều đó có thể sai, dựa trên những gì kiểm tra của đống được hiển thị. Tôi tự hỏi nếu hầu hết các JVM có vấn đề với phân bổ ít hơn một byte cho các biến.

+4

"một kiểu nguyên thủy boolean là 1 bit" phải là lỗi đánh máy rất nhỏ :) Không có vấn đề làm thế nào ảo JVM, nó phải tính toán boolean arithmetics bằng cách sử dụng thanh ghi CPU và ALU. –

1

Boolean đại diện cho một chút thông tin, nhưng "kích thước" của nó không phải là thứ được định nghĩa chính xác, theo hướng dẫn của Sun Java. Boolean literals chỉ có hai giá trị có thể là đúng và sai. Xem Java Data Types để biết chi tiết.

Các vấn đề liên quan