Stack lưu biến local + tham chiếu, cấp riêng mỗi thread, tự giải phóng khi method kết thúc (LIFO). Heap lưu object thật, chia sẻ giữa mọi thread, do Garbage Collector dọn.
java
void demo() {
int x = 5; // x nằm trên STACK
Person p = new Person(); // tham chiếu p ở stack, object Person ở HEAP
} // hết method: x + p rời stack, object chờ GCVì sao tách: stack nhanh (chỉ dịch con trỏ) nhưng nhỏ + ngắn hạn theo method; heap lớn, sống lâu, nhưng cần GC nên chậm hơn.
Lưu ý:
- Đệ quy quá sâu → StackOverflowError (tràn stack).
- Quá nhiều object sống lâu → OutOfMemoryError: Java heap space (tràn heap).
- 2 biến cùng trỏ 1 object trên heap → sửa qua biến này, biến kia thấy đổi theo.
Tóm lại: primitive + reference ở stack, object luôn ở heap. "Java pass-by-value" = copy cái reference, không copy object.