Backend

99 Ngày Java — Ngày 79: JVM Flags và Tuning cơ bản

SSite Admin
14 tháng 10, 2026 2 phút đọc 4 lượt xem
99 Ngày Java — Ngày 79: JVM Flags và Tuning cơ bản

Tuning JVM không bắt đầu bằng một danh sách cờ dài. Đầu tiên xác định giới hạn bộ nhớ máy hoặc container, độ trễ mục tiêu, throughput và triệu chứng hiện tại. Sau đó đặt vài cờ có mục đích, thu số liệu và thay đổi từng biến một. Java 21 có mặc định tốt cho nhiều dịch vụ; đo trước khi bỏ mặc định.

JVM Flags và Tuning cơ bản

1. Heap chỉ là một phần bộ nhớ tiến trình

-Xms đặt heap ban đầu; -Xmx đặt trần heap. Tiến trình còn dùng metaspace, thread stacks, direct buffers và native memory, nên Xmx không được bằng giới hạn RAM/container. Chừa biên cho hệ điều hành, sidecar và đột biến. Nếu chạy trong container, kiểm tra giới hạn thực và đo RSS cùng heap usage.

java -Xms512m -Xmx2g   -XX:+HeapDumpOnOutOfMemoryError   -XX:HeapDumpPath=/var/dumps   -Xlog:gc*:file=/var/log/app-gc.log:time,level,tags   -jar app.jar

2. Chọn GC theo mục tiêu

G1 là mặc định thông dụng của HotSpot trong Java 21, cân bằng throughput và pause. ZGC hướng tới pause rất ngắn, nhưng phải đo CPU và bộ nhớ bổ sung. Tên collector không đủ để chứng minh nó tốt hơn: chạy tải đại diện, so p95/p99 latency, throughput, pause và footprint. Giữ bản cấu hình cũ để quay lại.

java -XX:+UseG1GC -jar app.jar
java -XX:+UseZGC -XX:+ZGenerational -jar app.jar
# Java 21: generational ZGC is available; check measured trade-offs.

3. Đọc GC log trước khi tăng heap

Nhìn tần suất thu gom, pause, heap trước/sau và mức đáy sau mỗi lần thu. Nếu đáy tăng đều, có đối tượng sống lâu tích lũy; nếu heap đầy nhưng throughput giảm vì GC liên tục, cần xem phân bổ và retention. Tăng Xmx có thể chỉ trì hoãn OOM. So với JFR allocation và histogram để tìm lớp tăng nhanh.

jcmd <pid> VM.flags
jcmd <pid> GC.heap_info
jcmd <pid> GC.class_histogram | head -20

4. Điều tra OOM có thứ tự

Đọc thông điệp sau OutOfMemoryError: Java heap space, Metaspace hay unable to create native thread chỉ các hướng khác nhau. Giữ heap dump đủ an toàn để phân tích bằng MAT; tìm dominator, retained size và path to GC roots. Nếu container bị OOM killer giết mà không có Java exception, xem giới hạn bộ nhớ và native allocation. Sau sửa, lặp lại tải gây lỗi để xác nhận.

  • Dump có thể chứa token và dữ liệu cá nhân; hạn chế truy cập và xóa sau phân tích.

  • Thay một cờ mỗi lần, lưu số liệu trước/sau.

Tuning là vòng lặp giả thuyết, đo, thay đổi và đo lại. Ngày 80 đi sâu vào một nguyên nhân heap tăng lâu dài: memory leak.

Tài liệu đối chiếu

  • https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html

  • https://docs.oracle.com/en/java/javase/21/troubleshoot/troubleshooting-memory-leaks.html

S

Site Admin

Engineer and writer. Building things with TypeScript and distributed systems.

Bình luận (0)

Bạn cần đăng nhập bằng Google để bình luận.

Hãy là người bình luận đầu tiên.

Bài viết liên quan

99 Ngày Spring — Ngày 79: RabbitMQ với Spring

Exchange, queue, binding, @RabbitListener, retry/DLX và cách chọn RabbitMQ hay Kafka.

14 thg 10, 20262 phút4
99 Ngày Java — Ngày 78: Bytecode và javap

Đọc javap -c -p -v, operand stack, constant pool và những gì compiler thật sự tạo ra.

13 thg 10, 20262 phút6
99 Ngày Spring — Ngày 78: Kafka với Spring

KafkaTemplate, @KafkaListener, JSON serialization, retry, DLT và xử lý trùng sự kiện.

13 thg 10, 20262 phút6