Bộ tiện ích dòng lệnh đi kèm JDK đóng vai trò nền tảng trong việc giám sát hiệu năng, phát hiện rò rỉ bộ nhớ và phân tích trạng thái đồng bộ hóa của ứng dụng Java. Các công cụ này thường được phân phối tại thư mục gốc bin của môi trường Java và được tối ưu để hoạt động trên các bản phát hành từ JDK 8 trở lên (có điều chỉnh cấu trúc từ JDK 11).
Khung cảnh quan công cụ
| Trình điều khiển | Mục đích chính | Dựa trên Attach |
|---|---|---|
jps | Liệt kê tiến trình Java khả kiến | Có |
jstat | Giám sát chỉ số GC, class loader, JIT | Có |
jstack | Xuất vết ngăn xếp luồng (Thread Dump) | Có |
jmap | Phân tích cấu trúc Heap & tạo dump | Có |
jcmd | Điều khiển đa năng (thế hệ mới) | Có |
jinfo | Đọc/ghi tham số khởi tạo runtime | Có |
jhat | Phân tích dump qua HTTP (đã ngưng) | Không |
jconsole | Bảng điều khiển GUI cơ bản | Có / JMX |
jvisualvm | Profilers nâng cao (cài rời) | Có |
Giới hạn kết nối Attach: Cơ chế này mặc định yêu cầu tài khoản thực thi phải trùng với tài khoản khởi tạo JVM và hệ thống phải cho phép ghi vào socket tạm thời tại /tmp/.java_pid<ID>. Môi trường container hóa, hệ điều hành tối giản (Alpine) hoặc phân vùng chỉ đọc thường gây ra ngoại lệ từ chối truy cập.
Chi tiết thực thi từng công cụ
1. jps – Tra cứu tiến trình
jps [các_cờ] [hostid]
-q: Chỉ trả về mã định danh tiến trình-m: Hiển thị đối số truyền vào phương thức khởi tạo-l: In đường dẫn JAR hoặc package hoàn chỉnh-v: Liệt kê toàn bộ cờ JVM được áp dụng
APP_PROCESS=54321
jps -lv | grep $APP_PROCESS
# Kết quả: 54321 io.platform.core.Boot -XX:+UseZGC -Xms1g -Xmx2g
Khi triển khai trên Docker/Kubernetes, nếu danh sách trả về trống, nguyên nhân thường đến từ lớp cách ly PID namespace hoặc thiếu năng lực NET_ADMIN.
2. jstat – Thống kê chỉ số thời gian thực
Đây là công cụ siêu nhẹ, lý tưởng để theo dõi nhịp độ thu gom rác và tải lớp mà không gây gánh nặng cho hệ thống.
Giám sát chu trình GC
TARGET_PID=54321
jstat -gc $TARGET_PID 2000 5
Các cột dữ liệu được chuẩn hóa sang KB. Một số thông số trọng yếu:
S0C/S1C&S0U/S1U: Công suất và dung lượng sử dụng vùng SurvivorEC/EU: Không gian EdenOC/OU: Vùng Old GenerationMC/MU: MetaspaceYGC/YGCT&FGC/FGCT: Tần suất và tổng thời gian xử lý bộ nhớCCSC/CCSU: Không gian nén lớp
jstat -gcutil $TARGET_PID 1000 10 | tail -n 1
Cờ -gccapacity giúp theo dõi sự thay đổi công suất heap theo thời gian, trong khi -compiler cung cấp thống kê biên dịch JIT.
3. jstack – Xuất trạng thái luồng xử lý
jstack [các_cờ] $TARGET_PID
-l: Mở rộng thông tin về lock cơ chếjava.util.concurrent-F: Chế độ cưỡng chế (triệt tiêu bằng ptrace khi tiến trình treo)
jstack -l $TARGET_PID | awk '/"http-nio"/,/^$/' > /var/log/thread_slice.txt
Nếu gặp lỗi không mở được socket kết nối, phương án dự phòng an toàn là gửi tín hiệu SIGQUIT bằng kill -3 $TARGET_PID. Dữ liệu vết luồng sẽ được ghi trực tiếp vào luồng log tiêu chuẩn của ứng dụng.
4. jmap – Khảo sát bản đồ bộ nhớ
Công cụ này cho phép kiểm tra cấu hình heap hoặc xuất toàn bộ trạng thái đối tượng ra tệp nhị phân để phân tích tĩnh.
Thống kê phân bố đối tượng
jmap -histo:live $TARGET_PID | sort -nr -k 2 | head -n 15
Tham số :live chỉ đếm các đối tượng còn sống, nhưng điều này bắt buộc JVM phải thực hiện chu trình dọn dẹp toàn diện. Đầu ra bao gồm: thứ tự, số lượng instance, tổng byte và tên lớp.
Xuất file Heap Dump
DUMP_PATH="/opt/dumps/heap_$(date +%Y%m%d).hprof"
jmap -dump:live,format=b,file=$DUMP_PATH $TARGET_PID
Cảnh báo hiệu năng: Thao tác này kích hoạt cơ chế Stop-The-World. Tuyệt đối không thực hiện tùy tiện trên môi trường sản xuất đang chịu tải giao dịch.
5. jcmd – Bộ điều khiển đa năng hiện đại
Được giới thiệu từ JDK 7, jcmd tích hợp hầu hết chức năng của các công cụ cũ bằng cú pháp thống nhất, độ bảo mật cao và khả năng tương thích tốt hơn.
jcmd $TARGET_PID help
| Hoạt động | Cú pháp thay thế |
|---|---|
| In vết luồng | jcmd $TARGET_PID Thread.print -l |
| Khởi động GC | jcmd $TARGET_PID GC.run |
| Đọc tham số VM | jcmd $TARGET_PID VM.flags -all |
| Thuộc tính hệ thống | jcmd $TARGET_PID VM.system_properties |
| Đếm bộ nhớ native | jcmd $TARGET_PID VM.native_memory summary |
jcmd $TARGET_PID PerfCounter.print | grep /Threads/
Ưu điểm nổi bật là không tạo tệp tạm thời trung gian và hoạt động ổn định ngay cả trong môi trường cách ly chặt chẽ.
6. jinfo – Quản lý tham số runtime
jinfo -flags $TARGET_PID
jinfo -flag MaxMetaspaceSize $TARGET_PID
jinfo -flag +UnlockDiagnosticVMOptions $TARGET_PID
Hầu hết các cờ cấu hình không cho phép thay đổi khi đang chạy. Chỉ một số ít tham số boolean liên quan đến logging hay dump mới hỗ trợ điều chỉnh động.
7. Công cụ trực quan hóa & Phân tích dump
jconsole cung cấp giao diện nhẹ để giám sát MBean, CPU và bộ nhớ qua kết nối trực tiếp hoặc JMX. jvisualvm mạnh mẽ hơn với profiler tích hợp nhưng đã bị tách rời từ JDK 11. Đối với môi trường server không có bàn phím/màn hình, nên ưu tiên các lệnh dòng hoặc tích hợp endpoint giám sát qua HTTP.
Chú ý: jhat đã bị loại bỏ từ JDK 9. Các phương án thay thế tiêu chuẩn là Eclipse MAT, VisualVM hoặc bộ công cụ thương mại như JProfiler.
Khuyến nghị vận hành & Tối ưu
- Containerization: Ưu tiên
jcmd. Nếu Attach bị chặn, dùngkill -3. Kích hoạt-XX:+PreserveFramePointerđể hỗ trợ công cụ hiệu năng hệ thống như perf. - Quyền truy cập: Cần đảm bảo user thực thi lệnh trùng với user chạy Java. Trong Kubernetes, có thể dùng
execvới ngữ cảnh root tạm thời để vượt qua giới hạn socket. - Tác động hiệu năng: Các lệnh in luồng gần như không gây trễ. Ngược lại, dump heap dạng live hoặc histogram live sẽ kích hoạt chu trình thu gom toàn diện và làm gián đoạn dịch vụ.
- Chênh lệch phiên bản: JDK 17 đã mặc định bật hỗ trợ container. JDK 9+ đã loại bỏ
jhatvàjvisualvmkhỏi gói cài đặt chuẩn để giảm kích thước runtime.
Bảng tra cứu nhanh theo tình huống
| Kịch bản xử sự cố | Lệnh đề xuất |
|---|---|
| Liệt kê tiến trình Java đang chạy | jps -lv |
| Theo dõi tỷ lệ sử dụng Heap & Old Gen | jstat -gcutil $TARGET_PID 2s |
| CPU bất thường, tìm luồng tắc nghẽn | jcmd $TARGET_PID Thread.print -l hoặc kill -3 |
| Nghi ngờ rò rỉ bộ nhớ, xem phân bố lớp | jmap -histo:live $TARGET_PID | sort -nr -k 2 |
| Tạo bản dump heap để phân tích tĩnh | jmap -dump:live,format=b,file=/tmp/heap.hprof $TARGET_PID |
| Kiểm tra cờ khởi động đang áp dụng | jcmd $TARGET_PID VM.flags -all |
| Giám sát bộ nhớ Native (NMT) | jcmd $TARGET_PID VM.native_memory summary.diff |