NỘI DUNG BÀI VIẾT
Máy ảo Java (JVM) là gì?
Ngôn ngữ máy bao gồm những chỉ thị (instruction) rất đơn giản mà CPU máy tính có thể thực hiện trực tiếp. Tuy nhiên, hầu hết các chương trình đều được viết bằng các ngôn ngữ lập trình bậc cao như Java hay C++. Một chương trình viết bằng ngôn ngữ bậc cao cần được dịch sang ngôn ngữ máy trước khi có thể được chạy trên máy tính. Việc dịch này do trình biên dịch thực hiện. Để chạy trên các loại máy tính với các ngôn ngữ máy khác nhau, cần đến các trình biên dịch phù hợp với loại ngôn ngữ máy đó.
Có một lựa chọn khác thay vì biên dịch chương trình viết bằng ngôn ngữ bậc cao. Thay vì dùng một trình biên dịch để dịch thẳng toàn bộ chương trình, ta có thể dùng một trình thông dịch, nó dịch từng chỉ thị một và chỉ dịch khi cần đến. Một trình thông dịch là một chương trình hoạt động gần như một CPU với một dạng chu trình nạp-và-thực-thi (fetch-and-execute). Để thực thi một chương trình, trình thông dịch lặp đi lặp lại chuỗi công việc: đọc một chỉ thị từ trong chương trình, xác định xem cần làm gì để thực hiện chỉ thị đó, và rồi thực hiện các lệnh mã máy thích hợp để thực hiện chỉ thị đó.
Một công dụng của trình thông dịch là để thực thi các chương trình viết bằng ngôn ngữ bậc cao, chẳng hạn như ngôn ngữ Lisp. Công dụng thứ hai là chúng cho phép ta chạy một chương trình ngôn ngữ máy dành cho một loại máy tính này trên một loại máy tính hoàn toàn khác. Ví dụ, có một chương trình tên là “Virtual PC” chạy trên các máy tính cài hệ điều hành Mac OS, đó là một trình thông dịch thực thi các chương trình mã máy viết cho các máy tính tương thích IBM PC. Nếu ta chạy “Virtual PC” trên một máy Mac OS, ta có thể chạy bất cứ chương trình PC nào, trong đó có cả các chương trình viết cho Windows.
Những người thiết kế Java chọn cách tổ hợp giữa trình biên dịch và trình thông dịch. Các chương trình viết bằng Java được biên dịch thành mã máy, nhưng đây là loại ngôn ngữ máy dành cho loại máy tính không tồn tại – loại máy “ảo” này được gọi là Máy ảo Java (Java Virtual Machine – JVM). Ngôn ngữ máy dành cho máy ảo Java được gọi là Java bytecode, hay ngắn gọn là bytecode. Để chạy được các chương trình Java trên một loại máy tính bất kì, người ta chỉ cần một trình thông dịch dành cho Java bytecode, trình thông dịch này giả lập máy ảo Java theo kiểu mà Virtual PC giả lập một máy tính PC. Máy ảo Java cũng chính là tên gọi dành cho trình thông dịch bytecode thực hiện nhiệm vụ giả lập, do đó ta nói rằng một máy tính cần một máy ảo Java để chạy các chương trình Java.
Tất nhiên, mỗi loại máy tính cần một trình thông dịch Java bytecode khác, nhưng một khi đã có một trình thông dịch như vậy, nó có thể chạy một chương trình Java bytecode bất kì. Và cũng chính chương trình Java bytecode đó có thể chạy trên bất cứ máy tính nào có một trình thông dịch Java bytecode. Đây chính là một trong các đặc điểm quan trọng của Java: một chương trình sau khi biên dịch có thể chạy trên nhiều loại máy tính khác nhau.
Tại sao lại cần dùng Java bytecode
Có nhiều lý do tại sao nên dùng mã trung gian là Java bytecode thay cho việc phân phát mã nguồn chương trình Java và để cho mỗi người tự biên dịch nó sang mã máy của máy tính họ đang dùng. Thứ nhất, trình biên dịch là một chương trình phức tạp trong khi trình thông dịch chỉ là một chương trình nhỏ và đơn giản. Viết một trình thông dịch cho một loại máy tính mới dễ hơn là viết một trình biên dịch. Thứ hai, nhiều chương trình Java cần được tải xuống từ mạng máy tính. Việc này dẫn đến các mối quan tâm dễ thấy về bảo mật: ta không muốn tải về và chạy một chương trình sẽ phá hoại máy tính hoặc các file trong máy tính của ta. Trình thông dịch bytecode hoạt động với vai trò bộ đệm giữa máy tính của ta và chương trình ta tải về. Nó có thể bảo vệ ta khỏi các hành động nguy hiểm tiềm tàng của chương trình đó.
Khi Java còn là một ngôn ngữ mới, nó đã bị chỉ trích là chạy chậm. Do Java bytecode được thực thi bởi một trình thông dịch, có vẻ như các chương trình bytecode không bao giờ có thể chạy nhanh bằng các chương trình đã được biên dịch ra ngôn ngữ máy của chính máy tính mà chương trình đang chạy trên đó. Tuy nhiên, vấn đề này đã được giải quyết gần như toàn bộ bằng việc sử dụng trình biên dịch JIT (just-in-time compiler) cho việc thực thi Java bytecode. Trình biên dịch JIT dịch Java bytecode thành mã máy. Nó làm việc này trong khi thực thi chương trình. Cũng như một trình thông dịch thông thường, đầu vào cho một trình biên dịch JIT là một chương trình Java bytecode, và nhiệm vụ của nó là thực thi chương trình đó. Nhưng trong khi thực thi chương trình, nó dịch một phần của chương trình ra mã máy. Những phần được biên dịch này khi đó có thể được thực thi nhanh hơn là so với khi chúng được thông dịch. Do một phần của chương trình thường được thực thi nhiều lần trong khi chương trình chạy, một trình biên dịch JIT có thể cải thiện đáng kể tổng thời gian chạy của chương trình.