Java virtual Machine và Cơ chế hoạt động

JVM - Java virtual machine
Có thể dịch là máy ảo java

Như bạn thấy mỗi hệ điều hành chạy chương trình của nó với một mã máy khác nhau đó là mã bytecodes. Windows được biên dịch dưới dạng exe còn Linux là .ELF vì vậy hầu hết các phần mềm gặp khó khăn khi viết ra để sử dụng trên nhiều hệ điều hành.
Máy ảo java được sinh ra với 3 mục đích chính:

  • dịch mã java ra mã máy chạy được trên các hệ điều hành khác nhau
  • tăng tốc độ
  • Nâng cao độ bảo mật và tránh virus phá source code

JVM có 3 thành phần chính: ̀

  • Class Loader: Tìm kiếm và load các file .class vào vùng nhớ của java dưới dạng bytecode
  • 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.

Mình vẽ = pain các bạn thông cảm:
Hình ảnh mình họa java thực thi file .java sang mã bytecode bằng trình biên dịch JAVAC chuyển thành mã máy qua compiler JIT

Sau khi Classloader làm xong nhiệm vụ của mình các file sẽ được máy ảo JVM cung cấp bộ nhớ tương ứng với chúng.

  • Class area: đúng như tên gọi của nó, là vùng nhớ cấp phát cho class(Method) trong đó lại phân chia thành heap, stack, PC register, native method stack

  • Heap: Là nơi các đối tượng khởi tạo bằng toàn tử "new "sẽ được lưu ở đây tại thời điểm chương trình chạy

  • Stak : 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.

  • PC register : Khi JVM thực thi mã, một thanh ghi cục bộ có tên “Program Counter” được sử dụng. Thanh ghi này trỏ tới lệnh đang thực hiện. Khi cần thiết, có thể thay đổi nội dung thanh ghi để đổi hướng thực thi của chương trình. Trong trường hợp thông thường thì từng lệnh một nối tiếp nhau sẽ được thực thi.

  • native method: Nơi chứa tất cả các method native trong chương trình

  • 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.

Ví dụ: Person person = new Person ();
Heap: lưu đối tượng Person khi ta “new Person ();”
Stack: lưu tham chiếu “person ”.
Perm: lưu thông tin về Class “Person ”.

Execution Engine:
Sau khi lưu Dữ liệu xong chương trinh JVM sẽ biên dịch file .java thành dạng file .class bytecode bằng trình biên dịch javac

Khi file .class được hoàn thành chương trình tiếp tục sử dụng compiler “Just In Time-JIT”. Các trình duyệt thông dụng như Netscape hay IE đều có JIT bên trong để tăng tốc độ thực thi chương trình Java. Mục đích chính của JIT là chuyển tập lệnh bytecode thành mã máy cụ thể cho từng loại CPU. Các lệnh này sẽ được lưu trữ và sử dụng mỗi khi gọi đến.

3: Bởi vì các file .java đều được chuyển sang mã bytecode nên trong quá trình chạy không sợ virus có thể tấn công nên Java được coi là ngôn ngữ có độ bảo mật cao nhất hiện nay

9 Likes

@codocntt hy vọng bài viết này giúp bạn hiểu về JVM và phương thức nó hoạt động

2 Likes

Is JIT an interpreter???

2 Likes

Srr mình viết không rõ ràng chỗ đó, Trong JVM gồm JIT is a Complier và Interpreter chứ không phải JIT is an Interpreter

Mình khai báo int a = 0; thì biến a được tạo ở chỗ nào bạn? :smiley:

Biến địa phương được lưu trữ ngầm ở tầng stack.

không code java nhưng cũng vào hóng tí. :Dwink:

1 Like

Cho em hỏi. Giả như method của một object chứa trên heap được gọi mà lại tham chiếu đến instance variable của object đó. Thì khi được chuyển sang stack. Method đó tham chiếu đến biến instance của object đó theo cơ chế nào ạ? Em cám ơn!

Method tham chiếu đến Instance variable của Object chứa nó thì mới nghe lần đầu. Ý bạn là method đó truy cập biến instance ? Nếu vậy thì mình xin giải thích:
Giả sử mình lệnh này:

Bird cucky = new Bird();
cucky.fly();

và method fly() của class Bird:

void fly(){
    this.isFlying = true;
    ...
}

Ở đây cucky là 1 biến reference, chứ không phải là 1 object, biến này chỉ trỏ tới object đó thôi, tùy theo nơi nó được khai báo thì sẽ được chứa ở stack hoặc heap. Nếu bạn gọi method fly() từ cucky, thì fly() sẽ được vào stack, và bản thân cucky truy cập isFlying của object nó đang trỏ.

Bài viết hữu ích, mình mới tập tễnh học nên đọc những bài như vậy sẽ làm rõ được nhiều vấn đề về hoạt động của máy tính cũng như liên quan đến code thế nào.

Mình có tham khảo bài này, cũng viết khá nhiều http://coding-geek.com/jvm-memory-model/

Còn mình nghĩ cái phần này có liên quan đến phân bổ của phần cứng, nên nếu hiểu thêm chút về kiến thức hoạt động của phần cứng sẽ làm rõ hơn cơ chế của nó.

Đúng ý em muốn hỏi là vậy đấy. Tuy nhiên vấn đề là khi mình gọi fly(); fly() được đưa qua stack, còn biến isFlying đi kèm theo object nên được đặt ở heap. Thứ liên kết duy nhất giữa hai vùng nhớ này là biến reference cucky. Và với việc thực hiện xong hàm fly ở stack, biến isFlying bên heap cũng thay đổi giá trị. Vậy cơ chế tương tác của frame bên stack với object bên heap là như nào ạ? Em có thêm mấy vấn đề cần làm rõ là :1.Object khi được tạo ra bằng new thì trong memory của nó chứa cái gì? ( em đọc ở một số tài liệu là chứa field và một bảng con trỏ, trỏ tới method nó nắm giữ, không biết đúng không ) 2. Giả sử isFlying và fly() được thừa kế từ super class. Trong đó isFlying là private, còn fly() thì public bình thường. Khi chuyển qua stack làm sao khi đứng trên stack nó biết được là nó được truy cập isFlying cho dù cucky là object gọi nó còn không thể truy cập?



http://www.informit.com/articles/article.aspx?p=31755&seqNum=8

chỗ này em thấy sai sai ở trên thì ghi

vậy đáng lẽ lúc này phải có file .class rồi chứ còn chuyển gì nữa …

Lúc này là lúc nào? Bạn đó nói là file .class đã được biên dịch rồi còn gì.

Java sẽ compile source code của bạn (.java) sang bytecode (.class) . JVM sẽ thông dịch bytecode (.class) ra mã máy và thực thi

1 Like
  1. vậy JIT sẽ chứa Class Loader và Execution Engine luôn phải không ?
  2. có cách nào can thiệp vào file bytecode không ( tức là sau khi đã compile rồi mình có chỉnh sửa gì đó và không muốn phải compile lại toàn bộ mà chỉ muốn sửa 1 vài chổ thôi có được không ? )
  3. instance variable sẽ được lưu ở vùng nhớ nào ?

thì ngay chỗ này bạn ấy viết dư Execution Engine , chứ Execution Engine có liên quan gì đến lưu dữ liệu đâu …

Được!
Nhưng bạn phải là anh này

Và hiểu được cái này:

:smile:

Đùa thui: Nó ở level tương đương assembly, mình nghĩ có thể “đào bới” đc…

1 Like

cảm ơn vì đã giúp mình thông não :smiley:

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?