2012-01-27 28 views
10

Làm thế nào lớn, theo byte, là một nguyên thủy đóng hộp như java.lang.Integer hoặc java.lang.Character trong Java?Chi phí lưu trữ cho nguyên thủy đóng hộp trong Java là bao nhiêu?

An int là 4 byte, con trỏ thông thường cũng là 4 byte (nếu không được JVM nén). Là chi phí cho một số nguyên (không có bộ nhớ đệm) do đó 4 bytes + 4 bytes = 8 bytes? Có trường nào ẩn hơn trong đối tượng hộp hoặc chi phí phát sinh thêm liên quan đến các đối tượng không (nghĩa là có chi phí chung cho các đối tượng mà tôi không biết?).

Tôi không quan tâm đến vấn đề bộ nhớ đệm. Tôi biết rằng số nguyên trong một phạm vi nhất định được lưu trữ bởi JVM.

Người ta có thể thuật lại câu hỏi: Yếu tố tối đa sẽ được nhân với số lượng bộ nhớ được sử dụng cho các giá trị được đóng hộp so với giá trị nguyên thủy là gì?

EDIT: Tôi hiểu rằng nhiều triển khai của JVM tồn tại. Chi phí điển hình trong một triển khai HotSpot 32-bit điển hình là gì?

+7

Từ một góc độ nhất định, câu hỏi này không được trả lời vì phí trên một nguyên thủy đóng hộp không được chỉ định trong bất kỳ đặc điểm kỹ thuật nào. Nó có thể và sẽ thay đổi từ VM sang VM và nền tảng đến nền tảng. Nền tảng phần cứng có bộ nhớ được gắn thẻ thậm chí có thể có tổng chi phí bằng không. –

+0

trùng lặp của [Trong Java, cách tốt nhất để xác định kích thước của một đối tượng là gì?] (Http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to- xác định kích thước của một đối tượng). – DwB

+0

Tôi nghĩ rằng nó cũng có thể phụ thuộc vào ngữ cảnh bạn đang sử dụng int đóng hộp và bất kỳ tối ưu hóa trình biên dịch thời gian chạy được thực hiện. –

Trả lời

5

Đây là triển khai được xác định, do đó không có câu trả lời cụ thể. Nhưng tôi sẽ có thể trả lời nó cho Hotspot.

Điều bạn cần biết là: Hotspot luôn căn chỉnh đối tượng trên ranh giới 8byte. Hơn nữa có 2 từ trên không cho mỗi đối tượng. [1]

Nếu chúng ta đặt này cùng nhau chúng ta nhận được:

32bit VM: 4byte số nguyên + 2 từ đối tượng header = 12bytes. Đó không phải là bội số của 8, do đó, chi phí cho 1 số nguyên là bội số tiếp theo của 8: 16byte.

Máy ảo 64 bit: 4byte số nguyên + 2 từ = 20byte. Làm tròn lại: kích thước 24byte.

Kích thước của tham chiếu rõ ràng không phát thành kích thước của đối tượng, ngoại trừ nếu nó có tham chiếu đến các đối tượng khác không phải là trường hợp cho trình bao bọc int đơn giản. Nếu có, chúng tôi sẽ có 4byte cho mỗi tham chiếu cho 32bit và 4byte cho heaps < = 32gb với CompressedOops trên các JVM hiện đại (nếu không 8byte) cho các JVM 64 bit.

[1] Những người quan tâm có thể ghé qua mã trong share/vm/oops/oop.hpp

+1

vì lợi ích của sự hoàn chỉnh: nếu đối tượng được đồng bộ hóa, sẽ có một cấu trúc nguyên bản giữ mutex. – bestsss

+0

@bestsss Phải, hoàn toàn bỏ qua điều đó. Tôi nghĩ rằng ổ khóa nặng chỉ được tạo ra nếu chúng ta có một khóa contended (giả sử khóa thiên vị). Nếu chúng ta không, và không sử dụng hashcode của đối tượng, tôi nghĩ Hotspot sẽ lưu trữ tid trong tiêu đề đối tượng. Vì vậy, chỉ cần gọi 'đồng bộ hóa (foo) 'có thể không nhất thiết phải phân bổ bất kỳ bộ nhớ. – Voo

+0

có. khóa không thiên vị không được khuyến khích không thổi phồng tiêu đề nếu có yêu cầu System.identityHashCode(). Sau này được sử dụng (unofficiallY) để ngăn chặn khóa thiên vị trên một đối tượng được chọn. (i có nghĩa là chủ yếu là contented -> đôi khi tôi được sử dụng 'Object lock = new Byte (1)' để đơn giản hóa serialization – bestsss

1

Hơn thế nữa.

Mọi tham chiếu đối tượng đều có phí bổ sung, chẳng hạn như tham chiếu Lớp. Không chỉ vậy, con trỏ 4 byte của bạn không hoàn toàn chính xác. Đó là một tham chiếu, vì vậy nó là một ID cộng với một con trỏ, và con trỏ đó có thể là 8 byte nếu bạn đang ở trên một JVM 64 bit.

Dường như có sự khác biệt về triển khai VM. Cách tốt nhất để chắc chắn về điều này sẽ là kéo nó lên trong một hồ sơ.

Ước tính của tôi (Siêu SWAG) sẽ là. Tham chiếu đối tượng 16 byte (JVM 64 bit) Tham chiếu lớp 16 byte giá trị nguyên thủy 4 byte (Giả sử int.) Tổng số. 36 byte.

EDIT: Bây giờ bạn chỉ định JVM 32 bit, SWAG của tôi sẽ là 20 byte sử dụng cùng một phép toán ở trên.

+0

Tôi đã không có ý tưởng nhỏ như thế nào bạn đến với những con số .. nhìn vào nguồn Hotspot của tôi trong 'oop.hpp' cũng làm cho tôi không có khôn ngoan hơn (tôi chỉ có thể tìm thấy 2 con trỏ thông thường ở đó) – Voo

0

Tôi biết điều này không chính xác trả lời câu hỏi của bạn về chi phí lưu trữ nguyên thủy đóng hộp, nhưng tôi cảm nhận được từ câu hỏi của bạn mà bạn đang đặt câu hỏi hay không phải của bạn sử dụng chúng được bảo hành.

Dưới đây là một đoạn trích từ Effective Java (2nd Edition) bởi Joshua Bloch rằng sẽ giúp bạn quyết định:

"So when should you use boxed primitives? They have several legitimate uses. The first is as elements, keys, and values in collections. You can’t put primitives in collections, so you’re forced to use boxed primitives. This is a special case of a more general one. You must use boxed primitives as type parameters in parame- terized types (Chapter 5), because the language does not permit you to use primi- tives. For example, you cannot declare a variable to be of type Thread- Local<int>, so you must use ThreadLocal<Integer> instead. Finally, you must use boxed primitives when making reflective method invocations (Item 53).

In summary, use primitives in preference to boxed primitives whenever you have the choice. Primitive types are simpler and faster. If you must use boxed primitives, be careful! Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. When your program compares two boxed primitives with the == operator, it does an identity comparison, which is almost certainly not what you want. When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw a NullPointerException. Finally, when your program boxes primitive values, it can result in costly and unnecessary object creations."

Hy vọng rằng sẽ giúp.

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