JIT: biên dịch Just-In-Time là gì và cách hoạt động

Tác giả: IT Sectr Đã đăng: 2026-04-16 Thời gian đọc: 9 phút

JIT (Just-In-Time) là công nghệ biên dịch động chuyển đổi bytecode hoặc biểu diễn trung gian của chương trình thành các chỉ thị máy trực tiếp trong quá trình thực thi. Trong Android, trình biên dịch JIT xuất hiện lần đầu tiên trong phiên bản 2.2 Froyo như một phần của máy ảo Dalvik và tăng tốc thực thi ứng dụng lên 2–5 lần. Theo Google, 2024, JIT hiện đại trong ART kết hợp thông dịch với biên dịch có hồ sơ của các phương thức hot.

Những điểm chính

  • JIT — biên dịch Just-In-Time: chuyển đổi mã thành mã máy trực tiếp trong khi chương trình đang chạy.
  • Trong Dalvik, JIT biên dịch phương thức hot sau khi vượt quá ngưỡng gọi (~200 lần).
  • JIT giảm thời gian cài đặt và chiếm ít dung lượng hơn so với biên dịch AOT đầy đủ.
  • Nhược điểm chính là độ trễ khởi động: những giây đầu tiên ứng dụng chạy chậm hơn.
  • Trong ART hiện đại, JIT được sử dụng ở chế độ lai với tối ưu hóa AOT nền.

Biên dịch JIT là gì?

Just-In-Time (JIT) là một phương pháp biên dịch trong đó mã nguồn hoặc bytecode được chuyển đổi thành chỉ thị máy không phải trước (như với AOT), mà tại thời điểm gọi đầu tiên đến phần tương ứng của chương trình. Thuật ngữ “Just-In-Time” có nghĩa là biên dịch diễn ra “đúng lúc” — ngay trước khi thực thi.

Khái niệm JIT đã tồn tại từ những năm 1960, nhưng được chấp nhận rộng rãi với sự ra đời của Máy ảo Java vào năm 1995. JIT cho phép kết hợp tính khả chuyển của bytecode (viết một lần — chạy mọi nơi) với hiệu suất gần bằng mã gốc. Trong Java HotSpot VM, trình biên dịch JIT phân tích mã được thực thi và chỉ biên dịch những phần quan trọng nhất, tiết kiệm thời gian và bộ nhớ.

Cách hoạt động

Trình biên dịch JIT nhận bytecode đầu vào, thông dịch nó và đồng thời thu thập thống kê. Khi một phần mã (phương thức, vòng lặp) được gọi đủ thường xuyên, JIT quyết định biên dịch nó. Mã máy đã biên dịch được lưu trong bộ nhớ đệm — ở những lần gọi tiếp theo, phiên bản đã biên dịch được sử dụng. Điều này mang lại sự tăng tốc mà không cần biên dịch toàn bộ chương trình.

java
// Ví dụ: một phương thức trở nên hot sau nhiều lần gọi
public class HotMethod {
    private int compute(int n) {
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += i * i;
        }
        return sum;
    }
}

// Gọi 500 lần trong vòng lặp — JIT sẽ biên dịch compute
for (int t = 0; t < 500; t++) {
    hot.compute(1000);
}

JIT trong Android: Dalvik và ART

Trong Android, biên dịch JIT đã trải qua ba giai đoạn tiến hóa. Giai đoạn đầu — Dalvik không JIT (Android 1.0–2.1): thông dịch thuần túy bytecode DEX. Giai đoạn hai — Dalvik với JIT (Android 2.2–4.4): sự ra đời của trình biên dịch JIT, tăng tốc ứng dụng lên 2–5 lần. Giai đoạn ba — ART với JIT lai (Android 7.0+): sự trở lại của JIT với khả năng mới.

JIT trong Dalvik được triển khai như một trình biên dịch dựa trên dấu vết. Nó phân tích không phải các phương thức riêng lẻ, mà là chuỗi lệnh (dấu vết) thường được thực thi tuần tự. Điều này cho phép biên dịch toàn bộ đường dẫn thực thi, bao gồm nhiều phương thức. Cách tiếp cận này hiệu quả cho bộ xử lý di động với bộ nhớ đệm lệnh nhỏ, vì dấu vết đã biên dịch vừa với bộ nhớ đệm L1.

JIT trong ART hiện đại

Bắt đầu từ Android 7.0 Nougat, ART sử dụng JIT dựa trên phương thức — nó biên dịch các phương thức riêng lẻ dựa trên hồ sơ thực thi. JIT này hoạt động nhanh hơn đáng kể so với Dalvik JIT: thời gian biên dịch điển hình cho một phương thức là 0.5–1 ms so với 3–5 ms trong Dalvik. Mã đã biên dịch được lưu trữ trong một vùng nhớ riêng (bộ nhớ đệm mã JIT) thay vì heap ứng dụng, giảm sự phân mảnh.

Tham sốDalvik JITART JIT
LoạiDựa trên dấu vếtDựa trên phương thức
Tốc độ biên dịch3–5 ms/phương thức0.5–1 ms/phương thức
Ngưỡng biên dịch~200 lần gọiĐộng
Bộ nhớ đệm mãTrong heap ứng dụngBộ nhớ đệm mã JIT
Hồ sơ hóaNội bộTệp .prof bên ngoài

Phát hiện phương thức hot và ngưỡng biên dịch

Cơ chế trung tâm của JIT là phát hiện phương thức hot. Mỗi lần gọi phương thức làm tăng bộ đếm nội bộ. Khi bộ đếm vượt quá ngưỡng, phương thức được đánh dấu là “hot” và được gửi đi biên dịch. Trong Dalvik, ngưỡng cố định (~200 lần gọi). Trong ART, bộ đếm được cấu hình động tùy thuộc vào tài nguyên khả dụng của thiết bị.

Quá trình biên dịch bao gồm nhiều giai đoạn. Đầu tiên — phân tích bytecode: JIT kiểm tra luồng lệnh và xây dựng đồ thị luồng dữ liệu. Thứ hai — tối ưu hóa: nội tuyến các phương thức nhỏ, loại bỏ mã chết, gấp hằng số. Thứ ba — sinh mã: chuyển đổi đồ thị đã tối ưu thành chỉ thị máy cho kiến trúc CPU cụ thể (ARM, ARM64, x86).

java
// Minh họa nội tuyến — JIT sẽ nội tuyến thân phương thức
public int inlineExample() {
    return square(5);
}

private int square(int x) {
    return x * x;
} // JIT sẽ thay thế lời gọi bằng return 5 * 5;

OSR — Thay thế trên ngăn xếp

Một kỹ thuật đặc biệt của JIT — Thay thế trên ngăn xếp (OSR). Nếu một phương thức chứa vòng lặp dài không kết thúc sau hàng trăm lần lặp, JIT có thể biên dịch vòng lặp “tức thời” và thay thế phiên bản được thông dịch bằng phiên bản đã biên dịch ngay trong quá trình thực thi. OSR đặc biệt hiệu quả cho các tác vụ tính toán: kết xuất, xử lý ảnh, mã hóa.

JIT so với AOT: phân tích so sánh

JIT và AOT là hai cách tiếp cận biên dịch với các sự đánh đổi đối lập. JIT hy sinh tốc độ khởi chạy đầu tiên để có kích thước phân phối nhỏ gọn và khả năng thích ứng. AOT hy sinh thời gian cài đặt và dung lượng đĩa để có hiệu suất tối đa từ giây đầu tiên. Không có cách tiếp cận nào tốt hơn tuyệt đối — sự lựa chọn phụ thuộc vào kịch bản.

Lợi thế chính của JIT là tối ưu hóa thích ứng. JIT có thể sử dụng thông tin hồ sơ không có sẵn cho AOT: loại đối tượng chính xác, tần suất gọi thực tế, mẫu rẽ nhánh thực tế. Điều này cho phép áp dụng các tối ưu hóa mạnh mẽ không thể thực hiện với biên dịch tĩnh. Ví dụ, JIT có thể phi ảo hóa các lời gọi phương thức nếu chỉ có một loại người nhận được gặp trong thực tế.

Tiêu chíJITAOT
Thời gian cài đặtTức thìPhụ thuộc vào kích thước
Khởi chạy đầu tiênChậm hơn (khởi động)Nhanh
Dung lượng đĩaTối thiểu+15–30%
Khả năng thích ứngCaoThấp
Sử dụng CPUĐỉnh khi biên dịchỔn định

Khi nào nên chọn JIT

Biên dịch JIT được ưa chuộng khi việc triển khai nhanh và tiết kiệm dung lượng đĩa là quan trọng. Trong bối cảnh phát triển di động, JIT lý tưởng cho các ứng dụng được cập nhật thường xuyên (thử nghiệm A/B, bản vá nóng). JIT cũng thuận tiện trong quá trình phát triển, khi mã được xây dựng lại hàng chục lần mỗi ngày — mỗi giây tiết kiệm được khi biên dịch đẩy nhanh vòng lặp phản hồi.

Ưu điểm của biên dịch JIT

JIT mang lại cho nhà phát triển một số lợi thế thực tế. Đầu tiên — kích thước APK nhỏ. Với cách tiếp cận JIT, chỉ bytecode (DEX) được đóng gói trong APK, chiếm ít hơn 20–30% dung lượng so với mã gốc đã biên dịch. Đối với người dùng có bộ nhớ trong hạn chế, đây là một lợi thế đáng kể.

Lợi thế thứ hai là thích ứng với thiết bị. JIT biên dịch mã có tính đến kiến trúc CPU thực tế, dung lượng RAM và tải hiện tại. Ví dụ, trên thiết bị có 2 GB RAM, JIT có thể biên dịch ít tích cực hơn để tiết kiệm bộ nhớ, trong khi trên flagship có 12 GB, nó có thể áp dụng tất cả các tối ưu hóa có thể. Ngược lại, biên dịch AOT cố định quyết định tại thời điểm cài đặt.

Độc lập nền tảng

Bytecode vẫn độc lập với nền tảng, giúp đơn giản hóa việc phân phối ứng dụng. Một APK hoạt động trên các thiết bị ARM, ARM64 và x86, và JIT tạo mã gốc cho mỗi kiến trúc. Cách tiếp cận AOT sẽ yêu cầu bao gồm nhiều biến thể mã gốc trong APK (tăng kích thước) hoặc biên dịch một phiên bản riêng cho mỗi kiến trúc.

Nhược điểm và hạn chế của JIT

Nhược điểm chính của JIT là độ trễ khởi động. Người dùng trải qua sự chậm chạp trong những giây đầu tiên của ứng dụng trong khi JIT biên dịch các phương thức hot. Trong trò chơi, điều này biểu hiện như giật lag ở các cấp độ đầu. Trong ứng dụng có hoạt ảnh — các chuyển tiếp đầu tiên giữa các màn hình bị giật.

Nhược điểm thứ hai — tiêu thụ điện năng. Quá trình biên dịch làm CPU bị tải nặng, tăng mức tiêu thụ điện năng lên 10–20% trong thời gian khởi động. Trên các thiết bị chạy pin, điều này làm giảm thời lượng pin. Đặc biệt đáng chú ý trong các kịch bản khởi động lại ứng dụng thường xuyên (đa nhiệm với bộ nhớ hạn chế, nơi hệ thống dỡ và tải lại các tiến trình).

Phân mảnh bộ nhớ đệm

Một vấn đề khác — phân mảnh bộ nhớ đệm JIT. Mã đã biên dịch được lưu trữ trong một vùng nhớ liên tục. Khi các lớp mới được tải và các phương thức bổ sung được biên dịch, bộ nhớ đệm bị phân mảnh, làm tăng chi phí quản lý bộ nhớ. Trong Dalvik, vấn đề này được giải quyết bằng cách dọn dẹp bộ nhớ đệm định kỳ; trong ART, bộ nhớ đệm JIT được cấp phát riêng biệt với heap và sử dụng chiến lược chống phân mảnh riêng.

Chế độ lai: điều tốt nhất của hai thế giới

Cách tiếp cận hiện đại trong ART — biên dịch lai, kết hợp điểm mạnh của JIT và AOT. Trong quá trình cài đặt ứng dụng, không có biên dịch nào được thực hiện — chỉ xác minh bytecode (verify). Điều này đảm bảo cài đặt nhanh và sử dụng dung lượng tối thiểu. Những lần khởi chạy đầu tiên chạy ở chế độ thông dịch với biên dịch JIT các phương thức hot — người dùng có được hiệu suất chấp nhận được mà không cần chờ đợi lâu.

Đồng thời, một trình hồ sơ hóa nền thu thập dữ liệu về việc sử dụng thực tế. Sau 2–3 lần khởi chạy ứng dụng đầy đủ, hồ sơ đạt đến độ đầy đủ cần thiết, và hệ thống chạy dex2oat để biên dịch các phương thức hot thành mã gốc. Hoạt động này được thực hiện trong nền khi thiết bị không bị tải (đang sạc, màn hình tắt). Sau khi AOT nền hoàn tất, ứng dụng đạt được hiệu suất tương đương với biên dịch AOT đầy đủ.

bash
# Buộc bắt đầu biên dịch nền
adb shell cmd package compile -m speed-profile -f com.example.app

# Xem trạng thái biên dịch
adb shell cmd package dump-profiles com.example.app

Kết quả của cách tiếp cận lai

Theo Google I/O 2017, biên dịch lai đã giảm thời gian cài đặt ứng dụng từ 30–50% so với AOT thuần túy. Dung lượng đĩa chiếm trên phân vùng hệ thống giảm 20–30%. Đồng thời, hiệu suất sau biên dịch nền tương ứng với mức của AOT đầy đủ. Kịch bản duy nhất mà lai kém hơn AOT là lần khởi chạy đầu tiên ngay sau khi cài đặt: ứng dụng chạy ở chế độ JIT và có thể chậm hơn 10–15%.

Câu hỏi thường gặp

Biên dịch JIT là gì trong các thuật ngữ đơn giản?

JIT là cách tăng tốc chương trình mà mã được dịch sang ngôn ngữ máy không phải trước, mà theo từng phần trong khi chạy. Các phần thường xuyên nhất được biên dịch và lưu vào bộ nhớ đệm, trong khi các phần hiếm vẫn ở dạng ban đầu.

JIT khác AOT như thế nào?

JIT biên dịch mã trong quá trình thực thi, tiết kiệm dung lượng và tăng tốc cài đặt. AOT biên dịch tất cả mã trước — ứng dụng khởi động nhanh hơn nhưng yêu cầu nhiều dung lượng đĩa và thời gian cài đặt hơn.

Tại sao JIT bị loại bỏ khỏi Android?

JIT không bị loại bỏ — nó đã tiến hóa. Trong Android 5.0, Dalvik với JIT được thay thế bằng ART với AOT thuần túy. Trong Android 7.0, JIT quay trở lại ART như một phần của hệ thống lai, nơi nó hoạt động cùng với biên dịch AOT nền để có hiệu suất tối ưu.

JIT ảnh hưởng đến mức tiêu thụ điện năng như thế nào?

JIT làm tăng mức tiêu thụ điện năng từ 10–20% trong thời gian khởi động do tải CPU. Sau khi biên dịch phương thức hot hoàn tất, mức tiêu thụ điện năng trở lại bình thường. Chế độ lai của ART giảm thiểu các đỉnh này thông qua biên dịch nền.

Việc khởi động JIT có thấy được đối với người dùng không?

Có, trong các kịch bản có tính toán chuyên sâu. Người dùng có thể nhận thấy sự chậm chạp trong những giây đầu tiên vận hành ứng dụng hoặc khi bắt đầu trò chơi. Trong các phiên bản Android hiện đại (8.0+), chế độ lai giảm thiểu hiệu ứng này nhờ biên dịch có hồ sơ.

Tóm tắt

  • JIT (Just-In-Time) là biên dịch động chuyển đổi bytecode thành chỉ thị máy trong quá trình thực thi.
  • Trong Android, JIT đã tiến hóa: dựa trên dấu vết trong Dalvik → AOT đầy đủ → JIT+AOT lai trong ART hiện đại.
  • Phương thức hot được phát hiện qua bộ đếm gọi và được biên dịch khi vượt ngưỡng (~200 lần gọi).
  • OSR (Thay thế trên ngăn xếp) cho phép biên dịch các vòng lặp dài tức thời mà không làm gián đoạn thực thi.
  • Ưu điểm chính của JIT: kích thước APK nhỏ, cài đặt nhanh và thích ứng với thiết bị.
  • Nhược điểm chính: độ trễ khởi động, tiêu thụ điện năng đỉnh và phân mảnh bộ nhớ đệm.
  • Chế độ lai ART (Android 7.0+) giảm thời gian cài đặt 30–50% trong khi duy trì hiệu suất cao.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm