Trong Java, quản lý bộ nhớ là một quá trình quan trọng. Nó được quản lý bởi Java một cách tự động. JVM chia bộ nhớ thành hai phần: bộ nhớ Stack và bộ nhớ Heap. Theo quan điểm của Java, cả hai đều là vùng bộ nhớ quan trọng nhưng cả hai đều được sử dụng cho các mục đích khác nhau. Sự khác biệt chính giữa bộ nhớ Stack và bộ nhớ heap là Stack được sử dụng để lưu trữ thứ tự thực thi phương thức và các biến cục bộ, trong khi bộ nhớ heap lưu trữ các đối tượng và nó sử dụng cấp phát và giải phóng bộ nhớ động. Trong phần này, chúng ta sẽ thảo luận chi tiết về sự khác biệt giữa stack và heap.
Bộ nhớ Stack
Bộ nhớ Stack là một không gian vật lý (trong RAM) được phân bổ cho từng luồng(thread) trong thời gian chạy. Nó được tạo ra khi một chủ đề tạo ra. Việc quản lý bộ nhớ Stack tuân theo thứ tự LIFO (Last-In-First-Out) vì nó có thể truy cập được phạm vi Global. Nó lưu trữ các biến, tham chiếu đến đối tượng và kết quả từng phần. Bộ nhớ được phân bổ cho Stack tồn tại cho đến khi hàm kết thú. Nếu không có không gian để tạo các đối tượng mới, nó sẽ thrown java.lang.StackOverFlowError. Phạm vi của các yếu tố được giới hạn trong chủ đề của họ. JVM tạo một Stack riêng cho mỗi thread.
Bộ nhớ Heap
Nó được tạo khi JVM khởi động và được ứng dụng sử dụng trong thời gian ứng dụng đang chạy. Nó lưu trữ các object và các class trong JRE. Bất cứ khi nào chúng ta tạo các object, nó sẽ chiếm không gian trong bộ nhớ heap trong khi tham chiếu của đối tượng đó tạo trong vùng nhớ Stack. Vùng nhớ Heap không tuân theo bất kỳ thứ tự nào như Stack. Nó tự động xử lý các khối bộ nhớ. Điều đó có nghĩa là chúng ta không cần xử lý bộ nhớ theo cách thủ công. Để quản lý bộ nhớ một cách tự động, Java cung cấp trình thu gom rác( the garbage collector) để xóa các object không còn được sử dụng. Bộ nhớ được phân bổ cho heap tồn tại cho đến khi bất kỳ một sự kiện nào, chương trình kết thúc hoặc không còn bộ nhớ trống.
Các thành phần có thể truy cập trong toàn bộ ứng dụng. Đó là một không gian vùng nhớ chung được chia sẻ với tất cả các luồng thread. Nếu không gian heap đầy, nó sẽ throw java.lang.OutOfMemoryError.
Bộ nhớ heap được chia thành các vùng bộ nhớ sau:
- Young generation
- Survivor space
- Old generation
- Permanent generation
- Code Cache
(Chi tiết từng thành phần mình sẽ viết sau về bộ nhớ Heap ở bài riêng)
Hình ảnh sau đây cho thấy việc phân bổ bộ nhớ ngăn xếp và không gian heap.
Sự khác biệt giữa Bộ nhớ Stack và Bộ nhớ Heap
Tham số | Stack | Heap |
---|---|---|
Thành phần trong ứng dụng | Nó lưu trữ các mục có tuổi thọ rất ngắn như phương thức, biến và biến tham chiếu của đối tượng. | Nó lưu trữ các đối tượng và các lớp Java Runtime Environment (JRE). |
Thứ tự | Nó tuân theo thứ tự LIFO(Last Input First Outut) . | Nó không tuân theo bất kỳ thứ tự nào vì nó là cấp phát bộ nhớ động và không có bất kỳ mẫu cố định nào để cấp phát và hủy cấp phát các khối bộ nhớ. |
Tính Linh hoạt | Nó không linh hoạt vì chúng ta không thể thay đổi bộ nhớ được cấp phát. | Nó linh hoạt vì chúng ta có thể thay đổi bộ nhớ được phân bổ. |
Tính Hiệu quả | Nó có quyền truy cập, phân bổ và phân bổ nhanh hơn . | Nó có quyền truy cập, phân bổ và phân bổ chậm hơn . |
Kích thước bộ nhớ | Nó có kích thước nhỏ hơn . | Nó có kích thước lớn hơn . |
Cấu hình trong Java | Chúng ta có thể tăng kích thước dung lượng vùng nhớ Stack bằng cách sử dụng tùy chọn JVM -Xss. | Chúng ta có thể tăng hoặc giảm kích thước vùng nhớ Heap bằng cách sử dụng các tùy chọn – Xmx và -Xms JVM. |
Phạm vi truy cập | Các biến chỉ được truy cập trong luồng thread của chính nó | Các biến được truy cập trong tất cả các thread khác. |
Phân bổ không gian vùng nhớ | Khi một thread được khởi tạo, hệ điều hành sẽ tự động phân bổ vùng nhớ stack. | Để tạo không gian heap cho ứng dụng, Java gọi đến hệ điều hành trong quá trình run time. |
Phân bổ | Stack riêng biệt được tạo cho từng thành phần. | Nó được chia sẻ giữa tất cả các thread. |
Exception | JVM throw java.lang.StackOverFlowError nếu kích thước sử dụng vùng nhớ Stack lớn hơn giới hạn. Để tránh lỗi này, hãy tăng kích thước Stack. | JVM throw java.lang.OutOfMemoryError nếu JVM không thể tạo một native method mới. |
Phân bổ/Giải phòng bộ nhớ | Nó được thực hiện tự động bởi trình biên dịch(compiler). | Nó được thực hiện thủ công bởi lập trình viên(programmer). |
Chi phí | Chi phí của nó là ít hơn . | Chi phí của nó cao hơn so với Stack. |
Implementation | Thực hiện khó hơn. | Thực hiện dễ dàng hơn. |
Thứ tự phân bổ | Cấp phát bộ nhớ là liên tục theo thứ tự. | Bộ nhớ được phân bổ theo thứ tự ngẫu nhiên . |
Khả năng an toàn | An toàn cho thread vì mỗi luồng được phân bổ vùng nhớ stack riêng. | Không an toàn cho thread, vì vậy dùng lệnh synchronization để đồng bộ. |
Nguồn tham khảo:
Để lại một phản hồi
Bạn phải đăng nhập để gửi phản hồi.