Hướng dẫn vận hành bộ công cụ chẩn đoán JVM tích hợp

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ểnMục đích chínhDựa trên Attach
jpsLiệt kê tiến trình Java khả kiến
jstatGiám sát chỉ số GC, class loader, JIT
jstackXuất vết ngăn xếp luồng (Thread Dump)
jmapPhân tích cấu trúc Heap & tạo dump
jcmdĐiều khiển đa năng (thế hệ mới)
jinfoĐọc/ghi tham số khởi tạo runtime
jhatPhân tích dump qua HTTP (đã ngưng)Không
jconsoleBảng điều khiển GUI cơ bảnCó / JMX
jvisualvmProfilers nâng cao (cài rời)

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 Survivor
  • EC/EU: Không gian Eden
  • OC/OU: Vùng Old Generation
  • MC/MU: Metaspace
  • YGC/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 độngCú pháp thay thế
In vết luồngjcmd $TARGET_PID Thread.print -l
Khởi động GCjcmd $TARGET_PID GC.run
Đọc tham số VMjcmd $TARGET_PID VM.flags -all
Thuộc tính hệ thốngjcmd $TARGET_PID VM.system_properties
Đếm bộ nhớ nativejcmd $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ùng kill -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 exec vớ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ỏ jhatjvisualvm khỏ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ạyjps -lv
Theo dõi tỷ lệ sử dụng Heap & Old Genjstat -gcutil $TARGET_PID 2s
CPU bất thường, tìm luồng tắc nghẽnjcmd $TARGET_PID Thread.print -l hoặc kill -3
Nghi ngờ rò rỉ bộ nhớ, xem phân bố lớpjmap -histo:live $TARGET_PID | sort -nr -k 2
Tạo bản dump heap để phân tích tĩnhjmap -dump:live,format=b,file=/tmp/heap.hprof $TARGET_PID
Kiểm tra cờ khởi động đang áp dụngjcmd $TARGET_PID VM.flags -all
Giám sát bộ nhớ Native (NMT)jcmd $TARGET_PID VM.native_memory summary.diff

Thẻ: JVM Java Diagnostics memory management Performance tuning

Đăng vào ngày 16 tháng 7 lúc 10:48