| Stack overflow | Heap overflow | |
|---|---|---|
| Vùng nhớ | Stack (per-thread, ~512KB-1MB) | Heap (shared, GB) |
| Nguyên nhân | Đệ quy quá sâu, method call lồng | Quá nhiều object/memory leak |
| Exception | StackOverflowError | OutOfMemoryError: Java heap space |
| Phát hiện | Nhanh, rõ (stack trace dài) | Chậm, GC chạy hoài rồi mới throw |
| Debug | Đọc stack trace | Cần heap dump + Eclipse MAT |
java
// Stack overflow — đệ quy không có base case
void recurse() { recurse(); } // StackOverflowError ngay
// Heap overflow — phình memory
List<byte[]> leak = new ArrayList<>();
while (true) leak.add(new byte[1024 * 1024]); // OutOfMemoryError sau khi heap đầyPhòng tránh:
- Stack: tránh đệ quy sâu → chuyển iteration; nếu phải đệ quy, dùng tail recursion (Java chưa optimize tail-call, vẫn nên tránh).
- Heap: tăng -Xmx, fix memory leak, cache có eviction.
- Tăng stack size mỗi thread: -Xss512k (cẩn thận, mỗi thread × stack size = tổng memory).
| Stack overflow | Heap overflow | |
|---|---|---|
| Memory area | Stack (per-thread, ~512KB-1MB) | Heap (shared, GB) |
| Cause | Too-deep recursion, nested method calls | Too many objects / memory leak |
| Exception | StackOverflowError | OutOfMemoryError: Java heap space |
| Detection | Fast, clear (deep stack trace) | Slow, GC thrashes first |
| Debugging | Read the stack trace | Need a heap dump + Eclipse MAT |
java
// Stack overflow — recursion without a base case
void recurse() { recurse(); } // StackOverflowError immediately
// Heap overflow — runaway memory
List<byte[]> leak = new ArrayList<>();
while (true) leak.add(new byte[1024 * 1024]); // OutOfMemoryError once heap is fullPrevention:
- Stack: avoid deep recursion → use iteration; if recursion is required, prefer tail-recursive form (Java does not optimise tail calls, still safer to avoid).
- Heap: raise -Xmx, fix memory leaks, give caches an eviction policy.
- Tune per-thread stack with -Xss512k (careful: total = threads × stack size).