Thư viện tri thức trực tuyến
Kho tài liệu với 50,000+ tài liệu học thuật
© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

Cảm ơn bộ nhớ Hiểu cách JVM sử dụng bộ nhớ riêng trên Windows và Linux như thế nào pps
Nội dung xem thử
Mô tả chi tiết
Cảm ơn bộ nhớ
Hiểu cách JVM sử dụng bộ nhớ riêng trên Windows và Linux như thế nào
Andrew Hall, Kỹ sư phần mềm, IBM
Tóm tắt: Việc sử dụng hết heap (ND: heap là vùng lưu trữ đặc biệt trong bộ nhớ
được dùng để lưu giữ các tài liệu quan trọng như tài nguyên hệ thống và các loại
đối tượng khác nhau đang được sử dụng. Các heap đều được giới hạn trong phạm
vi 64k. Sau đây gọi là vùng heap) của Java™ không phải là nguyên nhân duy nhất
tạo ra một lỗi java.lang.OutOfMemoryError. Nếu bộ nhớ riêng (native memory)
dùng hết, có thể xảy ra các lỗi OutOfMemoryError (lỗi thiếu bộ nhớ) mà các kỹ
thuật gỡ lỗi thông thường của bạn sẽ không thể giải quyết được. Bài viết này giải
thích bộ nhớ riêng là gì, thời gian chạy của Java sử dụng nó như thế nào, việc
dùng hết nó sẽ như thế nào và làm thế nào để gỡ lỗi cho một lỗi
OutOfMemoryError trên Windows® và Linux®. Một bài viết khác của cùng tác
giả trình bày về các chủ đề tương tự nhưng dành cho các hệ thống AIX®.
Vùng heap của Java, nơi cấp phát không gian nhớ cho mọi đối tượng Java, là vùng
bộ nhớ gắn kết mật thiết nhất với bạn khi viết các ứng dụng Java. Máy ảo Java
(JVM) được thiết kế để cách ly chúng ta khỏi các điểm đặc thù của máy chủ, vì thế
hoàn toàn tự nhiên, có thể coi vùng heap như là một bộ nhớ. Chắc chắn là bạn đã
từng gặp phải một lỗi OutOfMemoryError của vùng heap của Java — gây ra bởi
một lỗ rò đối tượng hoặc do không tạo ra vùng heap đủ lớn để lưu trữ tất cả các dữ
liệu của bạn — và có lẽ bạn đã học được một vài thủ thuật để gỡ lỗi các kịch bản
này. Nhưng khi các ứng dụng Java của bạn xử lý nhiều dữ liệu hơn và nạp công
việc đồng thời nhiều hơn, bạn có thể bắt đầu nếm trải các lỗi OutOfMemoryError
không thể sửa chữa được khi sử dụng cả túi các thủ thuật thông thường của bạn —
đó là các kịch bản trong đó các lỗi xuất hiện ngay cả khi vùng heap của Java chưa
đầy. Khi điều này xảy ra, bạn cần phải hiểu những gì đang xảy ra bên trong Môi
trường thời gian chạy Java (Java Runtime Environment-JRE) của bạn.
Các ứng dụng Java chạy trong môi trường ảo hóa của thời gian chạy (runtime)
Java, nhưng thời gian chạy bản thân nó là một chương trình riêng được viết bằng
một ngôn ngữ (ví dụ như C), có tiêu dùng tài nguyên riêng, bao gồm cả bộ nhớ
riêng. Bộ nhớ riêng là bộ nhớ có sẵn dùng cho tiến trình thời gian chạy, để phân
biệt với bộ nhớ của vùng heap Java do một ứng dụng Java sử dụng. Mỗi tài
nguyên ảo — bao gồm cả vùng heap Java và các luồng (threads) Java — phải
được lưu trữ trong bộ nhớ riêng, cùng với các dữ liệu được các máy ảo sử dụng
khi nó chạy. Điều này có nghĩa rằng những hạn chế về bộ nhớ riêng, do phần cứng
của máy chủ và hệ điều hành (OS) áp đặt sẽ ảnh hưởng đến những gì bạn có thể
làm với ứng dụng Java của bạn.
Bài viết này là một trong hai bài trình bày cùng một chủ đề trên các nền tảng hệ
thống khác nhau. Trong cả hai bài, bạn sẽ tìm hiểu bộ nhớ riêng là gì, thời gian
chạy Java dùng nó như thế nào, việc sử dụng hết nó sẽ ra sao và làm thế nào để gỡ
lỗi một OutOfMemoryError riêng. Bài viết này trình bày Windows và Linux và
không tập trung vào bất kỳ thời gian chạy cụ thể nào. Bài viết của cùng một tác giả
trình bày về AIX và tập trung vào IBM® Developer Kit for Java (Bộ dụng cụ của
nhà phát triển của IBM cho Java). (Các thông tin trong bài viết đó về việc thực
hiện của IBM cũng đúng cho các nền tảng khác, không phải AIX, vì thế nếu bạn
sử dụng IBM Developer Kit cho Java trên Linux hay IBM 32-bit Runtime
Environment (Môi trường thời gian chạy 32-bit của IBM cho Windows), bạn có
thể nhận thấy bài viết đó cũng có ích).
Tóm tắt về bộ nhớ riêng
Tôi sẽ bắt đầu bằng cách giải thích những hạn chế về bộ nhớ riêng do hệ điều hành
và phần cứng nằm bên dưới áp đặt. Nếu bạn quen với việc quản lý bộ nhớ động
trong một ngôn ngữ như C, thì bạn có thể chuyển sang phần tiếp theo.
Những hạn chế về phần cứng
Rất nhiều hạn chế mà một tiến trình riêng phải trải qua là do phần cứng chứ không
phải do hệ điều hành áp đặt. Mỗi máy tính đều có một bộ xử lý và một số bộ nhớ
truy cập ngẫu nhiên (RAM), cũng được gọi là bộ nhớ vật lý. Một bộ xử lý dịch
dòng dữ liệu thành các lệnh để thực hiện; nó có một hoặc nhiều đơn vị xử lý để
thực hiện các phép tính số học số nguyên và dấu phẩy động cũng như nhiều phép
tính nâng cao hơn. Một bộ xử lý có một số thanh ghi — đó là các phần tử nhớ rất
nhanh được sử dụng làm nơi lưu trữ làm việc khi đang thực hiện các phép tính;
kích thước thanh ghi xác định số lượng lớn nhất mà một phép tính đơn lẻ có thể sử
dụng.
Bộ xử lý được kết nối với bộ nhớ vật lý bằng bus bộ nhớ. Độ lớn của địa chỉ vật lý
(địa chỉ được bộ xử lý sử dụng để lập chỉ số RAM vật lý) giới hạn dung lượng bộ
nhớ có thể được đánh địa chỉ. Ví dụ, một địa chỉ vật lý 16-bit có thể đánh địa chỉ
từ 0x0000 đến 0xFFFF, tạo ra 2^16 = 65536 vị trí nhớ duy nhất. Nếu mỗi địa chỉ
trỏ đến một byte của thiết bị lưu trữ, thì một địa chỉ vật lý 16-bit cho phép một bộ
xử lý đánh địa chỉ 64KB của bộ nhớ.
Các bộ xử lý được mô tả như là một số bit nhất định. Số này thường nói đến kích
thước của các thanh ghi, mặc dù có các trường hợp ngoại lệ — như 390 31-bit —
ở đây nó nói đến kích thước địa chỉ vật lý. Đối với các nền tảng hệ thống máy tính
để bàn và máy chủ, số này là 31, 32 hoặc 64; với thiết bị nhúng và các bộ vi xử lý,
nó có thể thấp tới mức bằng 4. Kích thước địa chỉ vật lý có thể giống như độ rộng
thanh ghi nhưng có thể lớn hơn hoặc nhỏ hơn. Hầu hết các bộ xử lý 64-bit có thể
chạy các chương trình 32-bit khi chạy một hệ điều hành phù hợp.
Bảng 1 liệt kê một số các kiến trúc Linux và Windows phổ biến với kích thước
thanh ghi và kích thước địa chỉ vật lý của chúng:
Bảng 1. Kích thước thanh ghi và địa chỉ vật lý của một số kiến trúc bộ xử lý
phổ biến
Kiến trúc Độ rộng thanh
ghi (bits) Kích thước địa chỉ vật lý (bits)
(Modern) Intel®
x86 32
32
36 nếu có phần mở rộng địa chỉ vật lý
(Pentium Pro và cao hơn)
x86 64 64 Hiện tại là 48-bit (có cơ hội để tăng lên sau)
PPC64 64 50-bit với POWER 5
390 31-bit 32 31
390 64-bit 64 64
Các hệ điều hành và bộ nhớ ảo
Nếu bạn đã viết các ứng dụng để chạy trực tiếp trên bộ xử lý mà không có một hệ
điều hành, bạn có thể sử dụng tất cả bộ nhớ mà bộ xử lý có thể đánh địa chỉ cho
chúng (giả sử có đủ RAM vật lý được đấu nối). Tuy nhiên, để tận hưởng các tính
năng như đa nhiệm và sự trừu tượng của phần cứng, gần như tất cả mọi người đều
sử dụng một hệ điều hành nào đó để chạy các chương trình của họ.
Trong các hệ điều hành (OS) đa nhiệm như Windows và Linux, có nhiều hơn một
chương trình sử dụng tài nguyên hệ thống, bao gồm cả bộ nhớ. Mỗi chương trình
cần phải được cấp phát các vùng nhớ vật lý để làm việc trong đó. Có thể thiết kế
một hệ điều hành sao cho mọi chương trình làm việc trực tiếp với bộ nhớ vật lý và
được tin tưởng sẽ chỉ sử dụng bộ nhớ mà nó đã được cấp. Một số hệ điều hành
nhúng làm việc giống như thế, nhưng sẽ là không thích hợp trong một môi trường
có nhiều chương trình không được thử nghiệm cùng với nhau vì bất kỳ chương
trình nào có thể làm hỏng bộ nhớ của các chương trình khác hoặc của chính hệ
điều hành.
Bộ nhớ ảo cho phép nhiều tiến trình xử lý dùng chung bộ nhớ vật lý mà không thể
làm hỏng dữ liệu của nhau. Trong một hệ điều hành có bộ nhớ ảo (như Windows,
Linux và nhiều hệ khác), mỗi chương trình có vùng địa chỉ ảo riêng của nó — một
vùng logic của các địa chỉ mà kích thước của nó do kích thước địa chỉ trên hệ
thống đó quyết định (như vậy là 31, 32 hoặc 64 bit cho các nền tảng máy tính để
bàn và máy chủ). Các vùng trong vùng địa chỉ ảo của một tiến trình có thể được
ánh xạ tới bộ nhớ vật lý, đến một tệp hoặc tới bất kỳ thiết bị lưu trữ có đánh địa
chỉ khác. Hệ điều hành có thể di chuyển dữ liệu được giữ trong bộ nhớ vật lý đến
và ra khỏi một vùng trao đổi (tệp trang (page file) trên Windows hay phân vùng
trao đổi (swap partition) trên Linux) khi nó không được sử dụng, để sử dụng bộ
nhớ vật lý một cách tốt nhất. Khi một chương trình cố gắng truy cập vào bộ nhớ
bằng cách sử dụng một địa chỉ ảo, hệ điều hành kết hợp với phần cứng trên chip
ánh xạ địa chỉ ảo đến vị trí vật lý. Vị trí đó có thể là RAM vật lý, một tệp hoặc tệp
trang/phân vùng trao đổi. Nếu một vùng bộ nhớ đã được di chuyển tới vùng trao
đổi, thì sau đó nó được nạp lại vào bộ nhớ vật lý trước khi được sử dụng. Hình 1
cho thấy bộ nhớ ảo làm việc như thế nào bằng cách ánh xạ các vùng của vùng địa
chỉ tiến trình xử lý đến các tài nguyên dùng chung: