Mục lục
Để tối ưu việc thực thi một chương trình trong java. JVM chia memory thành hai vùng stack và heap memory. Bất cứ lúc bạn bạn khởi tạo một biến, object, gọi một method mới hoặc khai báo một String hay thực hiện các phép tính toán thì JVM sẽ chỉ định các hành động này từ Stack và Heap.
Trong bài viết này chúng ta sẽ cùng nhau tìm hiểu khi nào Stack hoặc Heap được sử dụng và so sánh điểm khác nhau giữa chúng.
Stack memory trong java
Stack memory trong java được sử dụng để cấp phát vùng nhớ tĩnh và được sử dụng để thực thi một luồng (Trong lập trình đa luồng, mỗi luồng sẽ sở hữu một vùng nhớ Stack riêng). Nó chứa các tham số, các biến local và các tham chiếu đến các object được lưu trữ trong heap của method.
Stack hoạt động theo nguyên tắc Last-In-First-Out(LIFO). Khi một method được gọi một block sẽ được khởi tạo và thêm vào đầu Stack chứa tham số và các reference đến các object trong heap của method, khi method này thực hiện xong block cũng được xoá khỏi Stack và tiến hành gọi method tiếp theo trong Stack.
Các đặc điểm chính của Stack memory
- Tự tăng kích thước khi một method mới được gọi và giảm khi một method thực hiện xong.
- Các biến local bên trong Stack chỉ tồn tại khi method còn đang chạy.
- Nếu stack memory đầy Java sẽ quăng ra StackOverFlowError.
- Truy cập Stack memory sẽ nhanh hơn so với Heap.
- Mỗi thread trong java đều có riêng một Stack memory của nó.
Heap trong java
Heap được sử dụng để cấp phát vùng nhớ động cho các object được khởi tạo tại thời điểm runtime. Các object mới được khởi tạo sẽ luôn được lưu trữ trong Heap và các tham chiếu đến chúng sẽ được lưu trữ trong stack. Các object trong heap được truy cập ở bất cứ đâu trong ứng dụng.
Heap memory được chia thành các phần nhỏ hơn:
- Young Generation: Đây là nơi tất cả các object vừa được khởi tạo cho đến khi không có một tham chiếu nào tham chiếu đến nó thì sẽ được trình dọn rác thu gom.
- Old or Tenured Generation: Đây là nơi lưu trữ các object có vòng đời dài. Khi một object được khởi tạo và được đặt ở Young Generation chúng sẽ được đặt một ngưỡng cho thời gian sống, nếu vượt qua ngưỡng này thì chúng sẽ được đưa vào Old Generation.
- Permanent Generation: Đây là nơi lưu trữ các metadata cho runtime class và application method.
Các đặc điểm chính của Heap
- Nó được truy cập thông qua các cơ chế quản lý phức tạp bao gồm các phần Young, Old, Permanent Generation.
- Nếu Heap space đầy thì java sẽ quăng lỗi OutOfMemoryError.
- Truy cập dữ liệu trong vùng nhớ Heap sẽ lâu hơn so với Stack.
- Trái ngược với Stack, Heap không tự giải phóng vùng nhớ mà phải nhờ sự can thiệp của trình dọn rác java.
- Heap là một vùng nhớ chung cho toàn bộ Thread và chúng ta cần bảo vệ dữ liệu bằng cách đồng bộ hoá.
Ví dụ Stack và Heap
Cho đoạn code sau
class Person { int pid; String name; public Person(int pid, String name) { this.pid = pid; this.setName(name); } public void setName(String name) { this.name = name; } } public class Main { public static void main(String[] args) { int id = 23; String pName = "Jon"; Person p = null; p = new Person(id, pName); } }
Chúng ta cùng nhau phân tích đoạn code trên:
- Hàm main sẽ được gọi đầu tiên, một block sẽ được khởi tạo và thêm vào Stack để lưu trữ các giá trị và tham chiếu đối tượng.
- Giá trị của integer id = 23 được lưu trữ trực tiếp vào stack memory.
- Biến p tham chiếu đến object Person cũng được lưu trong Stack, trong khi object Person sẽ được lưu trong Heap.
- Method main() gọi constructor Person(int, String) khởi tạo 1 block và thêm vào đỉnh Stack đẩy Block của hàm Main() xuống, Block này sẽ lưu trữ:
- this tham chiếu đến object Person.
- pid = 23
- Tham chiếu đến String object name trong String pool trong heap memory thông qua tham số đầu vào name.
- Constructor lại gọi đến setName() method tạo thêm một block và thêm vào Stack đẩy block của constructor xuống. Block này sẽ lưu tham chiếu đến name trong String pool heap memory thông qua tham chiếu đầu vào name.
- Sau khi object Person được khởi tạo thì tất cả các instance của các biến sẽ được lưu vào heap memory. (id = 23, name=”Jon”)
Dưới đây là sơ đồ mô tả quá trình trên
Tóm lược
Stack và Heap là 2 cách mà java sử dụng để phân bổ bộ nhớ hiệu. Như vậy trong bài này chúng ta tìm hiểu được cơ chế hoạt động của Stack và Heap. Và hãy cố gắng ghi nhớ vì nó là một trong những chủ đề thường được đưa ra trong buổi phỏng vấn để xem ứng viên có hiểu nhưng thứ cơ bản nhất trong java hay không mà thông thường những người mới học java đều không để ý đến các kiến thức này.
Nguồn tham khảo
https://www.baeldung.com/java-stack-heap