Tất cả các chương trình muốn thực thi được thì phải được biên dịch ra mã máy. Mã máy của từng kiến trúc CPU của mỗi máy tính là khác nhau (tập lệnh mã máy của CPU Intel, CPU Solarix, CPU Macintosh … là khác nhau), vì vậy trước đây một chương trình sau khi được biên dịch xong chỉ có thể chạy được trên một kiến trúc CPU cụ thể nào đó. Đối với CPU Intel chúng ta có thể chạy các hệ điều hành như Microsoft Windows, Unix,Linux, OS/2, …
Chương trình thực thi được trên Windows được biên dịch dưới dạng file có đuôi .EXE còn trên Linux thì được biên dịch dưới dạng file có đuôi .ELF, vì vậy trước đây một chương trình chạy được trên Windows muốn chạy được trên hệ điều hành khác như Linux chẳng hạn thì phải chỉnh sửa và biên dịch lại.
Ngôn ngữ lập trình Java ra đời, nhờ vào máy ảo Java mà khó khăn nêu trên đã được khắc phục. Một chương trình viết bằng ngôn ngữ lập trình Java sẽ được biên dịch ra mã của máy ảo java (mã java bytecode). Sau đó máy ảo Java chịu trách nhiệm chuyển mã java bytecode thành mã máy tương ứng.Sun Microsystem chịu trách nhiệm phát triển các máy ảo Java chạy trên các hệ điều hành trên các kiến trúc CPU khác nhau.
JVM độc lập trên các hệ điều hànhMột Java Virtual Machine có 3 thành phần chính là:
- Class-Loader Subsytem : chuyên tìm kiếm và load các file .class vào vùng nhớ của Java.
- Runtime Data Area : vùng nhớ hệ thống cấp phát cho Java Virtual Machine.
- Execution Engine: chuyển các lệnh của JVM trong file .class thành các lệnh của máy, hệ điều hành tương ứng và thực thi chúng.
Các thành phần của máy ảo java (JVM)
Bộ nhớ trong Java JVM
Bộ nhớ trong Java JVM
Khi thực hiện cấp phát bộ nhớ, một đối tượng mới được tạo và đặt vào vùng nhớ Heap. Khi ứng dụng của bạn không còn tham chiếu tới đối tượng này nữa thì Java garbage collector cho phép xóa đối tượng này đi để sử dụng lại vùng nhớ đó.
Java Heap: JVM lưu tất cả đối tượng được tạo bởi toán tử “new” trong ứng dụng Java, vào vùng nhớ Heap tại thời điểm chạy.
Java Stack: Các phương thức và tham chiếu tới đối tượng địa phương được lưu trữ trong Stack. Mỗi Thread quản lý một stack. Khi phương thức được gọi, nó được đưa vào đỉnh của Stack. Stack lưu trữ trạng thái của phương thức bao gồm: dòng code thực thi, tham chiếu tới đối tượng địa phương. Khi phương thức chạy xong, vùng nhớ (dòng code thực thi, tham chiếu tới đối tượng địa phương) được đẩy ra khỏi stack và tự động giải phóng.
Java Perm: Lưu trữ thông tin của Class được nạp vào và một vài tính năng khác như StringPool (vùng nhớ của biến String) thường được tạo bởi phương thức String.interm(). Khi ứng dụng của bạn chạy, Perm space được lấp đầy nhanh chóng.
Heap: lưu đối tượng Dog khi ta “new Dog ();”
Stack: lưu tham chiếu “dog”.
Perm: lưu thông tin về Class “Dog”.
Tham khảo thêm
Video Giới thiệu về Java JVM.
(y)
ReplyDeleteCho hỏi, vì sao mình viết ngôn ngữ java ra, nó phải đi qua javac để thành bytecode rồi mới đến được JVM để dịch ra ngôn ngữ máy?
ReplyDeleteVì sao không chuyển thẳng từ ngôn ngữ java qua JVM? JVM cũng đi dịch từ bytecode, nghĩa là input của JVM là 1 ngôn ngữ, output nó là 1 ngôn ngữ khác. Sao JVM không dịch trực tiếp từ ngôn ngữ java mà phải dịch bytecode?
Cám ơn.
javac compile bytecode là để tăng tốc ứng dụng java khi chạy. Phiên bản hiện tại của Sun HotSpot JVM sử dụng một kỹ thuật gọi là Just-in-time (JIT) compilation để biên dịch thành bytecode để cho CPU và môi trường của từng OS dễ hiểu tăng tốc quá trình thực thi.
DeleteJIT - https://en.wikipedia.org/wiki/Just-in-time_compilation
Tuy nhiên vẫn có một số implements khác của JVM có thể biên dịch được trực tiếp code java thành mã máy như:
GNU Compiler for Java - http://gcc.gnu.org/java/
Bạn tham khảo thêm.
Thanks!