Backend

99 Ngày Java — Ngày 78: Bytecode và javap

SSite Admin
13 tháng 10, 2026 2 phút đọc 6 lượt xem
99 Ngày Java — Ngày 78: Bytecode và javap

Mã Java được compiler chuyển thành bytecode trong tệp .class, rồi JVM xác minh và thực thi hoặc JIT biên dịch. javap giúp nhìn qua lớp cú pháp nguồn: một phép cộng, vòng lặp hay lambda đã biến thành lệnh gì? Ta đọc đủ để giải thích hành vi, không cố suy đoán hiệu năng chỉ từ bytecode.

Bytecode và javap

1. Biên dịch và tháo mã

javac tạo tệp class; javap -c in lệnh, -p hiện cả thành viên private, -v hiện constant pool và metadata. Dùng -l nếu cần bảng dòng nguồn. Đọc đúng classpath và phiên bản JDK của tệp đang điều tra; bytecode do compiler khác nhau có thể khác dù hành vi tương đương.

javac --release 21 Counter.java
javap -c -p Counter
javap -v Counter | less
# For a package: javap -classpath out -c com.example.Counter

2. Operand stack và biến cục bộ

Nhiều lệnh JVM thao tác trên operand stack: iload_1 đẩy int từ local slot 1; iconst_1 đẩy số một; iadd lấy hai số trên đỉnh và đẩy tổng; istore_1 ghi kết quả. Local slot không phải tên biến nguồn. Với instance method, slot 0 thường là this; kiểu long và double chiếm hai slot.

static int plusOne(int x) { return x + 1; }
// 0: iload_0
// 1: iconst_1
// 2: iadd
// 3: ireturn

3. Constant pool và lời gọi hàm

Constant pool chứa tham chiếu tượng trưng tới lớp, field, method và hằng. invokestatic gọi static method; invokevirtual dispatch theo kiểu thực của receiver; invokeinterface dành cho interface. Lambda và nối chuỗi trên JDK hiện đại có thể dùng invokedynamic, vì thế không nên áp dụng cứng một ví dụ bytecode cũ cho Java 21.

# Inspect the constant-pool entry referenced by #12:
javap -v -p Counter | grep -A8 'Constant pool'
# invokevirtual #12 resolves a symbolic method reference.

4. Đọc có mục tiêu, đo khi tối ưu

Dùng javap để giải thích synthetic method, bridge method, boxing, lambda hoặc vì sao một hằng bị chép vào class gọi. Nhưng bytecode không phải mã máy cuối cùng: JIT có thể inline và tối ưu khác đi. Muốn kết luận hiệu năng, dùng JMH với warm-up hoặc JFR trên tải đại diện.

  • Câu hỏi về semantics: đọc bytecode.

  • Câu hỏi về tốc độ: đo runtime.

javap biến phỏng đoán về compiler thành điều quan sát được. Ngày 79 ta cấu hình giới hạn bộ nhớ và GC có phương pháp.

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

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

  • https://docs.oracle.com/javase/specs/jvms/se21/html/jvms-6.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 78: Kafka với Spring

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

13 thg 10, 20262 phút5
99 Ngày Spring — Ngày 77: Distributed Tracing với Micrometer và Zipkin

Trace/span, truyền context, Micrometer Tracing, Zipkin và cách đọc đường đi request qua service.

12 thg 10, 20262 phút6
99 Ngày Java — Ngày 77: String Pool và Interning

Literal, new String, intern(), equals so với == và khi chia sẻ chuỗi có thể phản tác dụng.

12 thg 10, 20262 phút6