Từ mã Java đến heap Java
Tóm tt:i này cung cp cho bn cái nhìn sâu sc v cách s dng b nh khi
viết mã Java™, bao gm chi phí s dng b nh trong việc đưa mt giá tr int vào
một đối tượng Integer (S nguyên), chi p v y quyền đối tượng và hiu qu b
nh ca các kiu B sưu tp (collection) khác nhau. Bn s tìm hiuch xác định
xem nhng vic không hiu qu xy ra đâu trong ứng dng ca bn và cách la
chọn đúngc bộ collection để ci thin mã ca mình.
Mc dù vic ti ưu hóa b nh khi viết ng dng không phải là điều mi m,
nhưng nó thường không được hiu rõ.i này trình y ngn gn cách s dng b
nh ca mt quá trình Java, sau đó đi sâu vào cách sử dng b nh ca mã Java
bn viết. Cui cùng, nó ch ra cách s dng b nh hiu qu hơn khi viết mã ng
dụng, đặc bit là trong lĩnh vực s dng các b collection Java chng hn như các
HashMap và các ArrayList.
Nn tng: Cách s dng b nh ca mt quá trình Java
Khi bn chy mt ng dng Java bngch thc hin lnh java trên dòng lnh
hoc bng cách bắt đầu mt s phn mm trung gian da trên Java, thi gian chy
Java to ra mt quá trình ca h điều hành — cũng giống như bn đang chạy mt
chương trình da trên-C. Trong thc tế, hu hết các máy ảo Java (JVM) được viết
ch yếu bng C hoc C++. Là mt quá trình (process) ca h điều hành, Java
runtime phải đối mt vi nhng hn chế v b nh tương t như bt k quá trình
khác nào: kh năng đánh đa ch được cung cp bi kiến trúc và vùng người dùng
được cung cp bi h điu hành.
Kh năng đánh đa ch b nh được cung cp bi kiến trúc ph thuc vào kích c
bit ca b vi x ví d, 32 hoc 64 bit hoc 31 bit trong trường hp máy tính
ln. S lưng các bit mà quá trình này có th x xác đnh phm vi ca b nh
mà b x lý có kh năng đánh địa ch: 32 bit cung cp mt phạm vi đánh địa ch
2^32, bng 4.294.967.296 bit, hoc 4GB. Phm vi đánh đa ch vi mt b x
64-bit ln hơn đáng kể: 2^64 bng 18.446.744.073.709.551.616 hoc 16 exabyte.
Mt s phạm vi đánh đa ch do kiến trúc ca b vi x cung cấp được s dng
bi chính h điu hành vi nhân của nó và (đối với các JVM được viết bng C
hoc C++) vi C runtime. S lượng b nh được h điều hành và C runtime s
dng ph thuc vào h điều hành đang được s dng, nhưng luôn quan trng là:
cách s dng mặc định của Windows là 2GB. Vùng đánh đa ch còn li được
gi vùng người dùnglà b nhsn cho quá trình thc tế đang chạy.
Tiếp theo, đối với các ứng dụng Java, vùng người dùng là bnhớ được sử dụng bởi
quá trình Java, thc sự bao gồm hai nhóm: (các) heap Java và heap nguyên gốc
(heap không phi của Java). Các giá trị thiết lập heap java của JVM kiểm soát kích
cỡ ca heap Java : -Xms và -Xmx tương ứng thiết lập heap java tối thiểu và tối đa.
heap nguyên gốc là vùng người dùng còn lại sau khi heap java đã được cấp phát ở
giá trị thiết lập kích cỡ tối đa. Hình 1 cho thấy một ví dụ về những gì mà điu này
có thgiống như với một quá trình Java 32-bit:
Hình 1. Ví d v cách b trí b nh cho mt quá trình (process) Java 32-bit
Trong Hình 1, việc sử dụng hệ điu hành và C runtime chiếm khoảng 1 GB trong
số 4GB vùng đa chỉ, Java heap sử dụng gần 2GB và heap nguyên gốc sử dụng
phần còn lại. Lưu ý rng bản thân JVM cũng sử dụng bộ nh— theo cùng cách mà
nhân ca hệ điều hành và C runtime làm và cũng lưu ý rng bộ nhmà JVM s
dụng là mt tập hợp con của heap nguyên gốc.
Cu to ca mt đối tượng Java
Khi mã Java của bạn sử dụng toán tử new để tạo ra một thể hiện của đối tượng
Java, có nhiều dữ liệu được cấp phát n là bạn có thể mong đợi. Ví dụ, bạn có thể
ngạc nhiên khi biết rằng tỷ lệ kích cỡ của một giá trị int trên một đối tượng Integer
đối tượng nhnhất có thể lưu giữ một giá trị int — thường là 1:4. Chi phí s
dụng bổ sung chính là siêu dliu mà JVM sử dụng để mô tả đối tượng Java, trong
trường hợp này là một Integer.
Số lượng của siêu dữ liệu đối tượng thay đổi theo từng phiên bn và nhà cung cấp
JVM, nhưng thường có:
Lớp (Class): Một con trỏ trỏ tới thông tin lớp, mô tả kiểu đối tượng. Ví dụ,
trong trường hợp ca một đối tượng java.lang.Integer, đây là một con trỏ đến
lớp java.lang.Integer.
C: (Flags): Một bộ sưu tập các cờ mô tả trạng thái của đối tượng, gồm
mã băm (hash code) cho đối tượng nếu nó chỉ có một và hình dạng (shape)
của đối tượng (tức là, dù đối tượng có là mt mảng hay không).
Khóa (Lock): Thông tin đồng bộ hóa cho đối tượng đó là, liu đối tượng
có được đồng bộ hóa không.
Sau đó siêu dữ liu đối tượng được tiếp theo bởi chính dữ liệu đối tượng, bao gồm
các trường được lưu trữ trong thể đối tượng. Trong trường hợp ca một đối
tượng java.lang.Integer, đây là một int đơn.
Vì vậy, khi bạn tạo một thể hin của một đối tượng java.lang.Integer khi chạy một
JVM 32-bit, cách bố trí của đối tượng có thể trông như Hình 2:
Hình 2. Ví d về cách b trí của một đối tượng java.lang.Integer cho mt q