NỘI DUNG BÀI VIẾT
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. Từ quan điểm của Java, cả hai đều là vùng 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à ngăn xếp đượ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 bộ nhớ động và định vị thỏa thuận. Trong phần này, chúng ta sẽ thảo luận chi tiết về sự khác biệt giữa bộ nhớ stack và bộ nhớ heap.
Stack Memory
Bộ nhớ ngăn xếp là một không gian vật lý (trong RAM) được phân bổ cho mỗi luồng tại thời gian chạy. Nó được tạo ra khi một luồng tạo ra. Quản lý bộ nhớ trong ngăn xếp tuân theo thứ tự LIFO (Last-In-First-Out) vì nó có thể truy cập được trên toàn cầu. 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 cấp phát cho các mạng ngăn xếp cho đến khi hàm trả về. Nếu không có không gian để tạo các đối tượng mới, nó sẽ ném ra java.lang.StackOverFlowError. Phạm vi của các phần tử được giới hạn trong các chủ đề của chúng. JVM tạo một ngăn xếp riêng biệt cho mỗi luồng.
Heap Memory
Nó được tạo khi JVM khởi động và được ứng dụng sử dụng miễn là ứng dụng chạy. Nó lưu trữ các đối tượng và các lớp JRE. Bất cứ khi nào chúng ta tạo các đối tượng, nó sẽ chiếm không gian trong bộ nhớ heap trong khi tham chiếu của đối tượng đó sẽ tạo ra trong ngăn xếp.
Nó không tuân theo bất kỳ thứ tự nào như ngăn xếp. Nó tự động xử lý các khối bộ nhớ. Nó có nghĩa là, chúng ta không cần phải 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 bộ thu gom rác để xóa các đối tượng không còn được sử dụng.
Bộ nhớ được cấp phát cho heap tồn tại cho đến khi bất kỳ sự kiện nào, chương trình kết thúc hoặc bộ nhớ trống không xảy ra. Các phần tử có thể truy cập toàn cầu trong ứng dụng. Nó là một không gian bộ nhớ chung được chia sẻ với tất cả các luồng. Nếu không gian heap đầy, nó sẽ ném ra 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
Hình ảnh sau đây cho thấy sự phân bổ của stack và heap.
Sự khác biệt giữa bộ nhớ ngăn xếp và bộ nhớ heap.
Bảng sau đây tóm tắt tất cả sự khác biệt chính giữa bộ nhớ ngăn xếp và bộ nhớ heap.
Parameter | Stack Memory | Heap Space |
---|---|---|
Application | Nó lưu trữ các mục có tuổi thọ rất ngắn như các phương thức, biến và biến tham chiếu của các đối tượng. | Nó lưu trữ các đối tượng và các lớp Java Runtime Environment (JRE). |
Ordering | Nó tuân theo thứ tự LIFO. | 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à phân bổ các khối bộ nhớ. |
Flexibility | 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 cấp phát. |
Efficiency | 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ổ giao dịch chậm hơn. |
Memory Size | Nó có kích thước nhỏ hơn. | Nó có kích thước lớn hơn. |
Java Options Used | Chúng ta có thể tăng kích thước ngăn xếp bằng cách sử dụng tùy chọn JVM -Xss. | Chúng tôi có thể tăng hoặc giảm kích thước bộ nhớ heap bằng cách sử dụng các tùy chọn -Xmx và -Xms JVM. |
Visibility or Scope | Các biến chỉ hiển thị với thread. | Nó được hiển thị cho tất cả các thread. |
Generation of Space | Khi một luồng được tạo, hệ điều hành sẽ tự động phân bổ ngăn xếp. | Để tạo không gian heap cho ứng dụng, trước tiên ngôn ngữ này sẽ gọi hệ điều hành tại thời điểm chạy. |
Distribution | Ngăn xếp riêng biệt được tạo cho từng đối tượng. | Nó được chia sẻ giữa tất cả các thread. |
Exception Throws | JVM ném lỗi java.lang.StackOverFlowError nếu kích thước ngăn xếp lớn hơn giới hạn. Để tránh lỗi này, hãy tăng kích thước ngăn xếp. | JVM ném java.lang.OutOfMemoryError nếu JVM không thể tạo một phương thức gốc mới. |
Allocation/ Deallocation | Nó được thực hiện tự động bởi trình biên dịch. | Nó được thực hiện thủ công bởi lập trình viên. |
Cost | Chi phí của nó là ít hơn. | Chi phí của nó cao hơn so với ngăn xếp. |
Implementation | Việc thực hiện nó thật khó. | Việc thực hiện nó rất dễ dàng. |
Order of allocation | Cấp phát bộ nhớ là liên tục. | Bộ nhớ được cấp phát theo thứ tự ngẫu nhiên. |
Thread-Safety | Nó an toàn theo luồng vì mỗi luồng có ngăn xếp riêng. | Nó không an toàn theo luồng, vì vậy cần phải đồng bộ hóa mã đúng cách. |
Hi vọng các bạn lập trình Java sẽ nắm rõ hơn về 2 loại bộ nhớ trong Java, từ đó có thể hiểu rõ cơ chế, nắm được các lỗi phát sinh từ bộ nhớ để tuỳ chỉnh. Chúc bạn học tốt.