56
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI VIỆN ĐIỆN TỬ - VIỄN THÔNG .........****......... BÁO CÁO BÀI TẬP LỚN HỆ ĐIỀU HÀNH Đề tài: Tìm hiểu về JVM (Java Virtual Machine) Hà Nội 5/2016

Tìm hiểu về jvm

  • Upload
    nt-thai

  • View
    35

  • Download
    3

Embed Size (px)

DESCRIPTION

Tìm hiểu về jvm

Citation preview

Page 1: Tìm hiểu về jvm

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

VIỆN ĐIỆN TỬ - VIỄN THÔNG

.........****.........

BÁO CÁO BÀI TẬP LỚN

HỆ ĐIỀU HÀNH

Đề tài: Tìm hiểu về JVM (Java Virtual Machine)

Hà Nội 5/2016

LỜI GIỚI THIỆU

Page 2: Tìm hiểu về jvm

Tìm hiểu JVM

Java là một ngôn ngữ lập trình hướng đối tượng (OOP) và dựa trên các lớp

(class). Khác với phần lớn ngôn ngữ lập trình thông thường, thay vì biên dịch mã

nguồn thành mã máy hoặc thông dịch mã nguồn khi chạy, Java được thiết kế để biên

dịch mã nguồn thành bytecode, bytecode sau đó sẽ được môi trường thực thi (runtime

environment) chạy.

Java được tạo ra với tiêu chí "Viết (code) một lần, thực thi khắp nơi" ("Write

Once, Run Anywhere" (WORA)). Chương trình phần mềm viết bằng Java có thể chạy

trên mọi nền tảng (platform) khác nhau thông qua một môi trường thực thi với điều

kiện có môi trường thực thi thích hợp hỗ trợ nền tảng đó. Môi trường thực thi của Sun

Microsystems hiện hỗ trợ Sun Solaris, Linux, Mac OS,FreeBSD & Windows. Ngoài

ra, một số công ty, tổ chức cũng như cá nhân khác cũng phát triển môi trường thực thi

Java cho những hệ điều hành khác như BEA, IBM, HP.... Trong đó đáng nói đến nhất

là IBM Java Platform hỗ trợ Windows, Linux, AIX & z/OS.

Java Virtual Machine (JVM) bản chất là một chương trình có thể thực thi các

đoạn mã lập trình của Java, và đặc điểm của những chương trình viết bằng Java là đều

có thể chạy trên bất kỳ môi trường nào, miễn là có cài máy ảo JVM trên đó. Việc này

sẽ tạo một động lực rất lớn thúc đẩy việc dùng lại các phần mềm Java đã được viết

trước đây và việc phát triển phần mềm trên iPhone và iTouch.

Vai trò to lớn, tính thực dụng và các ứng dụng rộng rãi của JVM đã nhận được

sự quan tâm sâu sắc của các kỹ sư, chuyên viên lập trình cũng như những người đam

mê công nghệ. Song việc tìm hiểu và tiếp cận JVM gặp nhều khó khăn do chưa có

nhiều tài liệu mô tả một cách chi tiết và rõ ràng. Cũng như thực tế có rất ít các trường

đại học dạy về vấn đề này. Do đó qua tìm hiểu kết hợp sự hướng dẫn cũng như giúp đỡ

của thầy Vũ Song Tùng, chúng em đã đưa ra một bản báo cáo một cách cơ bản về

JVM. Hi vọng tài liệu này đóng góp một phần kiến thức cơ bản về JVM cho những ai

muốn tìm hiểu. bản báo cáo này vẫn còn nhiều thiếu sót, chúng em mong có được sự

đóng góp ý kiến cũng như phản biện của người đọc để hoàn thiện hơn

Xin chân thành cảm ơn !

MỤC LỤC

Page | 2

Page 3: Tìm hiểu về jvm

Tìm hiểu JVM

LỜI GIỚI THIỆU..............................................................................................................2

I. Giới thiệu chung về Java Virtual Machine (JVM).............................................................5

1.1. Giới thiệu chung..........................................................................................................................5

1.1.1. Giới thiệu Java Virtual Machine (JVM).........................................................5

1.1.2. Máy ảo Java là gì?.............................................................................................5

1.1.3. Kiến trúc của máy ảo Java................................................................................6

1.2. Phương thức thực thi.................................................................................................................8

1.2.1. Quản lý bộ nhớ và dọn rác................................................................................8

1.2.2. Quá trình kiểm tra file .class............................................................................8

II. Tìm hiểu chi tiết về các thành phần trong Java Virtual Machine(JVM)................9

2.1. Tìm hiểu về Java Memory...................................................................................9

2.3. Các Kiểu Dữ Liệu...............................................................................................30

2.4. Word Size............................................................................................................33

2.5. Program Counter................................................................................................33

2.6. Threads (luồng trong Java)...............................................................................34

2.7. Native Method Interface....................................................................................36

PHỤ LỤC............................................................................................................................4

DANH SÁCH HÌNH VẼ...................................................................................................................4

DANH SÁCH BẢNG.........................................................................................................................4

TÀI LIỆU THAM KHẢO...............................................................................................38

PHỤ LỤC

DANH SÁCH HÌNH VẼ

Hình 1.1. Sơ đồ đơn giản về máy ảo Java………………………………….….…......7Page | 3

Page 4: Tìm hiểu về jvm

Tìm hiểu JVM

Hình 1.2. Sơ đồ bên trong của JVM………………..………………..……….…..…..7

Hình 2.1. Khu vực chia sẻ dữ liệu các thành phần…………...……..…….….……10

Hình 2.2. Hoạt động Stack trong JVM……………………..………….…….….….11

Hình 2.3. Mô tả một cách tiếp cận đối tượng của Heap…………………….…..…14

Hình 2.4. Một cách tiếp cận Object khác của Heap……….………………..….….15

Hình 2.5. Một cách tham chiếu đối tượng………………………….………..….….16

Hình 2.6. Đại diện của mảng trên Heap…………………………….………..….…17

Hình 2.7. Tham số phương thức trên phần biến địa phương của Java Stack..…20

Hình 2.8. Mô phỏng việc thêm 2 biến cục bộ……………………………….……...22

Hình 2.9. Mô phỏng hoạt động stack qua Ví Dụ………………………….….........23

Hình 2.10. Phân bố các khung hình từ ngăn xếp liền kề nhau…………….…...…24

Hình 2.11. Stack cho một thread khi Java gọi phương thức địa phương………...26

Hình 2.12. Các kiểu dữ liệu trong Java………………………………….….…...…31

DANH SÁCH BẢNG

Bảng 2.1. Phạm vi các kiểu dữ liệu trong máy ảo Java………………………...….33

Page | 4

Page 5: Tìm hiểu về jvm

Tìm hiểu JVM

I. Giới thiệu chung về Java Virtual Machine (JVM)

1.1. Giới thiệu chung

1.1.1. Giới thiệu Java Virtual Machine (JVM)

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 1 chương

trình sau khi được biên dịch xong chỉ có thể chạy trên 1 kiến trúc CPU cụ thể nào đó.

Đối với Intel chúng ta có thể chạy các hệ điều hành như Microsoft Windows, Unix,

Linux…

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 1 chương trình chạy trên Windows muốn chạy trên các hệ điều hành khác như

Linux phải chỉnh sửa biên 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 trên được

khắc phục. Một chương trình được 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 hiệ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.

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.

1.1.2. Máy ảo Java là gì?

Như đã biết, JVM bản chất là một chương trình có thể thực thi các đoạn mã lập

trình của Java, và đặc điểm của những chương trình viết bằng Java là đều có thể chạy

trên bất kỳ môi trường nào, miễn là có cài máy ảo JVM trên đó. Việc này sẽ tạo một

Page | 5

Page 6: Tìm hiểu về jvm

Tìm hiểu JVM

động lực rất lớn thúc đẩy việc dùng lại các phần mềm Java đã được viết trước đây và

việc phát triển phần mềm trên iPhone và iTouch.

Máy ảo là một phần mềm dựa trên cơ sở máy tính ảo. Nó có tập hợp các lệnh

logic để xác định các hoạt động của máy tính.Người ta có thể xem nó như một hệ điều

hành thu nhỏ. Nó thiết lập các lớp trừu tượng cho: Phần cứng bên dưới,hệ điều

hành,mã đã biên dịch.

Trình biên dịch chuyển mã nguồn thành tập các lệnh của máy ảo mà không phụ

thuộc vào phần cứng cụ thể. Trình thông dịch trên mỗi máy sẽ chuyển tập lệnh này

thành chương trình thực thi. Máy ảo tạo ra một môi trường bên trong để thực thi các

lệnh bằng cách:

Nạp các file.class

Quản lý bộ nhớ

Dọn "rác"

Việc không nhất quán của phần cứng làm cho máy ảo phải sử dụng ngăn xếp

để lưu trữ các thông tin sau:

Các "Frame" chứa các trạng thái của các phương pháp.

Các toán hạng của mã bytecode

Các tham số truyền cho phương pháp

Các biến cục bộ

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.

Một khái niệm thông dụng khác trong Java là trình biên dịch "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.

1.1.3. Kiến trúc của máy ảo Java

Hình 1.1 là sơ đồ đơn giản về máy ảo Java

Page | 6

Page 7: Tìm hiểu về jvm

Tìm hiểu JVM

Hình 1.1 Sơ đồ đơn giản về máy ảo Java

Đầu tiên sẽ là biên dịch file.java sang file.class và được máy ảo Java chuyển hoá thành

các mã máy tương ứng với các hệ điều hành tương ứng.

Để tìm hiểu sâu hơn chúng ta đi vào sơ đồ nội bộ của 1 máy ảo Java

Hình 1.2 Sơ đồ bên trong của Java Virtual Machine

Như trong hình ta thấy Java có 3 thành phần chính

1. Class Loader: Tìm kiếm và nạp các file.class vào vùng nhớ java

Page | 7

Page 8: Tìm hiểu về jvm

Tìm hiểu JVM

2. Data Area: Vùng nhớ hệ thống cấp phát cho Java Virtual Machine

3. Execution Engine: chuyển các lệnh của JVM trong file.class thành

mã máy tương ứng với các hệ điều hành

1.2. Phương thức thực thi

1.2.1. Quản lý bộ nhớ và dọn rác

Trong C, C++ hay Pascal người lập trình sử dụng phương pháp nguyên thủy để

cấp phát và thu hồi bộ nhớ ở vùng " Heap". Heap là vùng bộ nhớ lớn được phân chia

cho tất cả các Thread.

Để quản lý Heap, bộ nhớ được theo dõi qua các danh sách sau:

- Danh sách các vùng nhớ rảnh chưa cấp phát.

- Danh sách các vùng đã cấp

Khi có một yêu cầu về cấp phát bộ nhớ, hệ thống kiểm tra xem xét trong danh

sách chưa cấp phát để lấy ra khối bộ nhớ đầu tiên có kích cỡ sát nhất. Chiến thuật cấp

phát này giảm tối thiểu việc phân mảnh của Heap. "Coalescing" là kỹ thuật khác cũng

giảm thiểu việc phân mảnh của Heap bằng cách gom lại các vùng nhớ chưa dùng liền

nhau. Còn kỹ thuật sắp xếp lại các phần đã dùng để tạo vùng nhớ lớn hơn gọi là

"Compaction" Java sử dụng hai Heap riêng biệt cho cấp phát vùng nhớ tĩnh và vùng

nhớ động. Một Heap(Heap tĩnh) chứa các định nghĩa về lớp, các hằng và danh sách

các phương pháp. Heap còn lại(Heap động) được chia làm hai phần được cấp phát theo

hai chiều ngược nhau. Một bên chứa đối tượng còn bên kia chứa con trỏ trỏ đến đối

tượng đó.

"Handle" là cấu trúc bao gồm hai con trỏ. Một trỏ đến bảng phương pháp của đối

tượng, con trỏ thứ hai trỏ đến chính đối tượng đó. Chú ý rằng khi "compaction" cần

cập nhập lại giá trị con trỏ của cấu trúc" Handle". Thuật toán dọn rác có thể áp dụng

cho các đối tượng đặt trong Heap động. Khi có yêu cầu về bộ nhớ, trình quản lý Heap

trước tiên kiểm tra danh sách bộ nhớ chưa cấp phát. Nếu không tìm thấy khối bộ nhớ

nào phù hợp(về kích cỡ) thì trình dọn rác sẽ được kịch hoạt khi hệ thống rảnh. Nhưng

khi đòi hỏi bộ nhớ cấp bách thì trình dọn rác sẽ được kích hoạt ngay.

Trình dọn rác gọi hàm Finalize trước khi dọn dẹp đối tượng. Hàm này sẽ dọn

dẹp các tài nguyên bên ngoài như các file đang mở. Công việc này không được trình

dọn rác thực thi.Page | 8

Page 9: Tìm hiểu về jvm

Tìm hiểu JVM

1.2.2. Quá trình kiểm tra file .class

Việc kiểm tra được áp dụng cho tất cả các file .class sắp được nạp lên bộ nhớ để

đảm bảo tính an toàn.

Trình "Class Loader" sẽ kiểm tra tất cả các file .class không phụ thuộc hệ điều

hành với mục đích giám sát sự tuân thủ các nghi thức để phát hiện các file ,class có

nguy cơ gây hư hỏng đến bộ nhớ, hệ thống file cục bộ, mạng hoặc hệ điều hành. Quá

trình kiểm tra sẽ xem xét đến tính toàn vẹn toàn cục của lớp.

File .class bao gồm ba phần logic là:

1. Byecode

2. Thông tin về Class như phương pháp, giao diện và các giá trị được tập

hợp trong quá trình biên dịch.

3. Các thuộc tính về lớp.

Các thông tin của file . class được xem xét riêng rẽ trong các bảng như sau:

Bảng file chứa các thuộc tính

Bảng Method chứa các hàm của class

Bảng Interface chứa các giao diện và các hằng số

Quá trình kiểm tra file .class được thực hiện ở bốn mức:

• Mức đầu tiên thực hiện việc kiểm tra cú pháp để đảm bảo tính cấu trúc và

tính toàn vẹn cú pháp của file .class được nạp.

• Mức thứ hai sẽ xem xét file.class để đảm bảo các file này không vi phạm

các nguyên tắc về sự nhất quán ngữ nghĩa.

• Mức thứ ba sẽ kiểm tra bytecode. Trong bước này các thông tin so sánh sẽ

là số thông số truyền của hàm, khả năng truy xuất sai chỉ số của mảng, chuỗi, biểu

thức.

• Mức thứ tư sẽ kiểm tra trong thời gian thực thi để giám sát các việc còn

lại mà ba bước trên chưa làm. Ví dụ như liên kết tới các lớp khác trong khi thực thi,

hay kiểm tra quyền truy xuất. Nếu mọi điều thỏa mãn, lớp sẽ được khởi tạo.

II. Tìm hiểu chi tiết về các thành phần trong Java Virtual Machine (JVM)

2.1. Tìm hiểu về Java Memory

Mỗi khi máy ảo java (JVM) chạy một chương trình, nó cần bộ nhớ để lưu trữ

nhiều thứ bao gồm cả byte code và các thông tin nó lấy từ các file nạp, đối tượng

Page | 9

Page 10: Tìm hiểu về jvm

Tìm hiểu JVM

chương trình được khởi tạo, các tham số, các giá trị trả lại, các biến địa phương và các

kết quả trung gian trong quá trình tính toán. Các máy ảo Java nó tổ chức bộ nhớ thành

nhiều vùng dữ liệu theo thời gian.

Mặc dù khu vực vùng dữ liệu đó tồn tại trong một số hình thức của máy ảo

java, đặc điểm của chúng là khá trừu tượng. Mỗi vùng nhớ có một cách tổ chức khác

nhau giúp nhà thiết kế lựa chọn để triển khai công việc.

Một số vùng nhớ được truy cập được từ mọi thành phần nhưng có những vùng

nhớ thì không. Mỗi khi JVM nạp một file class nó sẽ phân tích thông tin về các loại dữ

liệu nhị phân chứa trong file class đó. Nó sẽ đặt các thông tin này vào 1 vùng nhớ

method area. Khi máy ảo hoạt động tất cả các đối tượng (object) sẽ được lưu vào vùng

nhớ Heap.

Hình 2.1 Khu vực chia sẻ dữ liệu các thành phần

Mỗi thread xuất hiện nó được ghi vào 1 thanh ghi pc(chương trình đếm) và Java

Stack. Nếu thread đang thực thi một phương thức của Java (không phải là phương thức

địa phương) giá trị của thanh ghi pc chỉ lệnh kế tiếp được thực thi. Mỗi thread Java

stack được lưu trữ trạng thái của Java (không có nguồn gốc) phương pháp gọi cho

Java. Trạng thái của phương pháp gọi Java bao gồm: các biến tại địa phương, các biến

của nó được dẫn, các giá trị trả về (nếu có) và các giá trị trung gian trong quá trình

thực hiện. Các trạng thái của phương thức gọi được lưu trữ phụ thuộc vào stack địa

phương, hoặc các khu vực bộ nhớ thực hiện các phụ thuộc khác.

Page | 10

Page 11: Tìm hiểu về jvm

Tìm hiểu JVM

Các Java Stack bao gồm các khung stack (khung). Một khung Stack chứa các

trạng thái của một chương trình gọi Java. Khi có một thread gọi một phương pháp nào

đó các máy ảo đẩy khung mới của chủ đề đó lên Java Stack. Khi chương trình này

được chạy xong máy ảo tiến hành loại bỏ khung của phương thức đó.

Các máy ảo Java không có các thanh ghi để lưu các giá trị trung gian. Các tập

lệnh sử dụng chính Stack để lưu các giá trị trung gian. Cách làm này được thực hiện

bởi các nhà thiết kế Java nhằm làm cho máy ảo Java được nhỏ gọn nhất để tạo điều

kiện có thể cài đặt sử dụng trên các kiến trúc nhỏ. Ngoài ra các kiến trúc stack dựa trên

các tập lệnh của máy ảo java tạo điều kiện làm việc tối ưu hoá thực hiện bằng cách

just-in-time và trình biên dịch hoạt động ở thời gian chạy trong khi thực thi máy ảo.

Hình 2.2 Hoạt động Stack trong JVM

Hình 2.2 là một hình ảnh thể hiện một trường hợp của máy ảo có 3 thread được

thực hiện trong đó có một thread 3 là phương thức địa phương. Khung stack cho

phương thức thực thi được hiện thi trong màu sáng. Đối với một Thread đang được

thực hiện một phương thức của Java , thanh ghi Pc chỉ lệnh kế tiếp được thực thi.

Page | 11

Page 12: Tìm hiểu về jvm

Tìm hiểu JVM

Trong hình 2.2 cũng như vậy thanh ghi pc được thể hiện trong một màu sáng. Bởi về

thread 3 được thực hiện là một phương thức bản địa, các nội dung thanh ghi pc của nó

– là màu tối (không xác định).

2.1.1. Bộ nhớ Heap

Bất cứ một lớp hay một mảng nào được tạo ra trong quá trình chạy của máy ảo

Java, bộ nhớ để lưu trữ tất cả các đối tượng là Heap. Java có chương trình chạy riêng

biệt nên không thể có việc hai chương trình Java khác nhau lại sử dụng chung một dữ

liệu, nhưng hai chủ đề trong cùng một ứng dụng có thể xung đột dữ liệu đó là việc bạn

phải quan tâm đến việc đồng bộ hoá và tiếp cận đa luồng cho các đối tượng sử dụng

trong chương trình Java của bạn.

Các máy ảo Java cấp phát heap cho các đối tượng mới nhưng không có hỗ trợ

phương thức cho người sử dụng giải phóng nó. Thông thường các máy ảo Java sẽ sử

dụng bộ thu dọn rác để quản lý Heap

a) Bộ thu dọn rác

Chức năng chính của chương trình là lấy lại các vùng nhớ đang được sử dụng bời

các đối tượng mà không còn được tham chiếu đến nữa khi JVM đang hoạt động. Nó

cũng có thể di chuyển các ứng dụng hay các đối tượng chạy để giảm phân mảnh.

Có thể bộ thu dọn rác hoạt động không đúng đặc điểm kỹ thuật của máy ảo Java.

Các đặc điểm kỹ thuật chỉ yêu cầu thực hiện quản lý Heap riêng của mình theo một số

phương pháp. Các đặc điểm kỹ thuật của máy ảo Java không nói có bao nhiêu bộ nhớ

phải được sử dụng để có sẵn đối tượng cho chương trình đang chạy. Nó không nói làm

thế nào để quản lí thực thi bộ nhớ Heap của nó, nó nói với các nhà thực hiện là chương

trình sẽ được cấp phát bộ nhớ nhưng không giải phóng nó.

Không có kỹ thuật thu dọn nào được quyết định bởi các đặc điểm kỹ thuật của máy

ảo Java. Nhà thiết kế sử dụng bất cứ kỹ thuật nào mà họ cho là phù hợp với mục tiêu

và với những hạn chế về trình độ của họ.

Khi một máy ảo cần một bộ nhớ cho một đối tượng mới, nó có thể làm mất dữ liệu

từ Heap mà đối tượng đang cư trú. Việc thu dọn rác và giải phóng bộ nhớ bị quản lí

bởi các đối tượng unreferenced có thể chăm sóc việc tìm kiếm và giải phóng. Triển Page | 12

Page 13: Tìm hiểu về jvm

Tìm hiểu JVM

khai cho phép người sử dụng hay lập trình có thể dễ dàng xác định 1 kích thước ban

đầu cho Heap.

b) Các đối tượng (Object)

Các đặc điểm kỹ thuật của máy ảo java là im các đối tượng trên Heap. Đối tượng

đại diện - một khía cạnh của thiết kế tổng thể - là quyết định của các nhà thiết kế thực

hiện.

Các dữ liệu chính phải bằng cách nào đó được đại diện cho mỗi đối tượng là các

biến được khai báo trong các class của đối tượng và tất cả các superclasses của nó.

Cho một tham chiếu đối tượng, các máy ảo phải nhanh chóng xác định vị trí các dữ

liệu mẫu cho đối tượng. Ngoài ra phải có một số cách để truy cập dữ liệu lớp của đối

tượng(được lưu trữ trong khu vực phương thức) cho tham chiếu đến đối tượng. Vì lý

do này cấp phát bộ nhớ cho một đối tượng thường bao gồm một số loại con trỏ vào

khu vực phương thức.

Một thiết kế Heap có thể chia heap ra làm hai thành phần : Một khu xử lý và một

khu đối tượng. Một tham chiếu đối tượng là một con trỏ có nguồn gốc từ một khu xử

lý. Một khu xử lý có hai thành phần: một con trỏ đến đối tượng mẫu trong khu đối

tượng và một con trỏ đế dữ liệu mẫu ở khu phương thức. Ưu điểm của hệ thống này là

làm cho nó dễ dàng chống lại việc phân mảnh Heap. Khi các máy ảo di chuyển đối

tượng ra một vị trí mới trong khu đối tượng nó chỉ việc trỏ đến nơi mới của đối tượng.

Nhưng bất lợi của phương pháp này là mỗi một lần truy cập vào dữ liệu lại yêu cầu sử

dụng 2 con trỏ. Hình ảnh sau đây thể hiện rõ ràng cách hoạt động của phương pháp

này.

Page | 13

Page 14: Tìm hiểu về jvm

Tìm hiểu JVM

Hình 2.3 Mô tả cách tiếp cận đối tượng của Heap

Một thiết kế khác là làm cho đối tượng tham chiếu một con trỏ có nguồn gốc từ

một gói dữ liệu đã có dữ liệu sẵn. Cách tiếp cận này đòi hỏi dereferencing chỉ có một

con trỏ để truy cập dữ liệu. Khi các máy ảo di chuyển đối tượng dẫn đến việc bị phân

mảnh Heap, nó phải cập nhập mỗi tham chiếu đến đối tượng mà bất cứ nơi nào trong

khu vực dữ liệu thời gian chạy. Cách tiếp cận này được thể hiện như sau.

Page | 14

Page 15: Tìm hiểu về jvm

Tìm hiểu JVM

Hình 2.4 Một cách tiếp cận Object khác của Heap

Các máy ảo cần nhận được đối tượng tham chiếu đến lớp kiểu dữ liệu của đối

tượng đó vì nhiều lý do. Khi một chương trình cố gắng để một đối tượng tham chiếu

đến một kiểu khác, các máy ảo phải kiểm tra xem các loại đang được tham chiếu đến

là class của đổi tượng tham chiếu hoặc là một trong các siêu kiểu của nó. Nó phải được

kiểm tra khi một chương trình được chạy hay một instanceof hoạt động . Trong cả hai

trường hợp, các máy ảo phải chọn lựa phương pháp nào để gọi không dựa trên tham số

nhưng trên lớp của đối tượng. Để làm điều này nó phải có quyền một lần nữa truy cập

vào các class dữ liệu nhất định chỉ có 1 tham chiếu đến đối tượng.

Một cách một thực hiện có thể kết nối với phương thức để đối tượng được tham

chiếu được hiển thị trong Hình 2.5 con số này cho thấy rằng con trỏ giữ cùng với các

dữ liệu ví dụ cho từng đối tượng điểm đến một cấu trúc đặc biệt. Cấu trúc đặc biệt này

có 2 phần

Một con trỏ có đầy đủ dữ liệu cho lớp đối tượng

Page | 15

Page 16: Tìm hiểu về jvm

Tìm hiểu JVM

Bảng các phương thức cho các đối tượng bảng phương thức là một mảng

của con trỏ đến dữ liệu cho mỗi phương thức. Các dữ liệu được trỏ đến bởi

bảng phương thức bao gồm:

o Các kích thước của toán hạng Stack và biến địa phương của phương

thức ngăn xếp

o ByteCode của phương thức

o Bảng các giá trị ngoại lệ

Điều này tạo đầy đủ thông tin để máy ảo gọi phương thức.

Hình 2.5 Một cách tham chiếu đến đối tượng

c) Đại diện mảng

Trong Java mảng là đối tượng đầy đủ. Giống như đối tượng mảng cũng được

lưu trữ

trên Heap. Cũng như đối tượng các nhà thiết kế thực hiện có thể quyết định cách mà

họ đại diện cho mảng trên heap.

Page | 16

Page 17: Tìm hiểu về jvm

Tìm hiểu JVM

Mảng có class liên quan đến class của chúng giống như bất kỳ đối tượng khác.

Tất cả các mảng có cùng kích thước và cùng loại sẽ cùng một lớp. Chiều dài của một

mảng (hay là độ dài kích thước của mảng đa chiều) không đóng vai trò nào trong việc

thành lập nên lớp mảng. Chiều dài của một mảng coi như là một phần dữ liệu của

mảng

Hình 2.6 Đại diện của mảng trên Heap

Các dữ liệu lưu trữ trên heap cho mỗi mảng là chiều dài của mảng, mảng dữ

liệu, và một số loại tham số lớp của mảng. Cho một tham chiếu đến mảng, các máy ảo

phải có khả năng xác định độ dài của mảng, để có được và cài đặt các phần tử của nó

bằng chỉ số(kiểm tra để chắc chắn không vượt quá giới hạn) và để gọi bất kỳ một

phương thức kê khai nào của đối tượng các lớp cha trực tiếp của tất cả các mảng.

2.2.2 Stack trong Java

Khi một thread được đưa ra, các máy ảo Java tạo ra một Java Stack mới cho

thread. Như đã đề cập trước đó một Stack lưu trữ trạng thái của một thread trong

khung rời rạc. Các máy ảo Java chỉ thực hiện hai hoạt động trực tiếp trên Stack: Đẩy

và Bật khung

Các phương thức đang được thực hiện bởi một thread là phương thức hiện

hành. Các khung stack cho các phương thức tại thời điểm là phương thức hiện tại. Các Page | 17

Page 18: Tìm hiểu về jvm

Tìm hiểu JVM

lớp chứa các phương thức hiện tại là lớp hiện tại và khu chứa các lớp hiện tại gọi là

khu hiện tại. Khi thực hiện một phương thức các máy ảo theo dõi các lớp hiện tại và

các khu hiện tại. Khi máy ảo gặp hướng dẫn hoạt động trên các dữ liệu được lưu trữ

trên các khung stack, nó thực hiện hoạt động trên khung hiện tại.

Khi một thread gọi một phương thức Java, máy ảo tạo ra và đẩy một khung mới

vào thread của Java Stack. Khung mới này sau đó trở thành nhưng khung hiện tại.

Phương thức thực hiện, nó sử dụng khung hình để lưu trữ các thông số, các biến địa

phương, tính toán trung gian và các dữ liệu khác.

Một phương thức có thể hoàn thành bằng một trong hai cách. Nếu một phương

thức hoàn thành bằng cách quay lại nó được cho là hoàn thành bình thường. Nhưng

nếu kết thúc bằng cách ném ra một ngoại lệ nó được cho là hoàn thành đột ngột. Khi

một phương thức hoàn thành cho dù là bình thường hay đột ngột các Java pops của

máy ảo sẽ loại bỏ khung của khương thức ra khỏi Java Stack. Các khung hình cho các

phương thức trước đó sẽ trở thành khung hiện tại.

Tất cả dữ liệu trên một thread của Java Stack là dựa trên một thread nào đó.

Không có cách nào để thread truy cập cũng như thay đổi Stack Java của một thread

khác. Bởi vì điều này bạn không bao giờ phải lo lắng đồng bộ hoá luồng truy cập đến

biến địa phương trong chương trình của bạn. Một khi thread gọi một phương thức biến

cục bộ của phương thức được lưu trữ trong một khung trên thread theo Java Stack. Chỉ

có phương thức của thread mới truy cập được vào biến địa phương trên thread đó.

Cũng giống như các phương thức và heap, Java stack và khung stack không

phải được tiếp giáp trong bộ nhớ. Khung có thể được phân bổ trên một Stack tiếp giáp

hoặc trên heap hoặc cả hai. Các cấu trúc dữ liệu thực tế được sử dụng đại diện cho

stack Java và khung Stack là quyết định của người thiết kế thực hiện. Triển khai có thể

cho phép người sử dụng hoặc lập trình xác định một kích thước ban đầu cho Stack

Java cũng như các giá trị kích thước max min.

a) The Stack Frame (Khung stack)

Các khung stack có 3 phần: các biến địa phương, toán hạng stack và khung dữ

liệu. Các kích thước của các biến địa phương và toán hạng stack phụ thuộc vào nhu

Page | 18

Page 19: Tìm hiểu về jvm

Tìm hiểu JVM

cầu của từng phương thức riêng lẻ. Các kích thước này được xác định tại thời điểm

biên dịch và đưa vào class dữ liệu cho từng phương thức. Kích thước của khung dữ

liệu là sự phụ thuộc

Khi máy ảo Java chạy sẽ là một phương thức Java, nó sẽ kiểm tra class dữ liệu để

xác định số lượng các từ theo yêu cầu của phương thức trong các biến địa phương và

toán hạng stack. Nó tạo ra một khung stack có kích thước thích hợp và đẩy vào Stack

Java.

b) Các biến địa phương

Phần biến địa phương của stack frame Java được tổ chức như một mảng số không

dựa trên các từ. Sử dụng một giá trị từ biến địa phương cung cấp một chỉ số vào mảng

zero-based. Giá trị kiểu int, float, reference và returnAddress chiếm một ô trong mảng

các biến địa phương. Giá trị kiểu byte, short và char được chuyển sang int trước khi

lưu vào biến địa phương. Giá trị của kiểu long và double chiếm 2 mục liên tiếp trong

mảng.

Phần biến cục bộ chứa các thông số của một số phương thức và các biến địa

phương. Trình biên dịch đặt các tham số vào mảng biến địa phương đầu tiên theo thứ

tự chúng được khai báo.Hình 2.7 cho thấy phần biến địa phương trong 2 phương pháp.

Page | 19

Page 20: Tìm hiểu về jvm

Tìm hiểu JVM

Hình 2.7 Tham số phương thức trên phần biến địa phương của Java Stack

Lưu ý rằng hình 2.7 cho thấy các tham số đầu tiên trong các biến địa phương cho

runInstanceMethod() là kiểu reference mặc dù không có các tham số như vậy xuất hiện

trong mã nguồn. Phương thức sử dụng thông tin này để truy cập các dữ liệu thể hiện

các đối tượng trên đó. Như bạn có thể thấy bằng cách nhìn vào các biến cục bộ của

runClassMethod() trong trong hình 2.7, các phương thức lớp không nhận được ẩn này.

Phương thức Class không được gọi trên đối tượng. Bạn có thể không trực tiếp truy cập

vào các biến cá thể của một class từ một phương thức vì không có sự kết hợp với các

phương thức gọi.

Cũng lưu ý rằng các loại byte, short, char và boolean trong mã nguồn mở trở thành

int s trong biến địa phương. Điều này cũng đúng với các toán hạng stack. Như đã đề

cập trước đó, boolean là loại không được hỗ trợ trong máy ảo Java. Trình biên dịch

luôn luôn sử dụng int s để đại diện cho giá trị boolean trong các biến địa phương hay

các toán hạng stack. Các kiểu byte, short và char tuy được hỗ trợ trực tiếp bởi máy ảo

Java. Chúng có thể được lưu trữ trên heap như các biến cá thể hoặc các phần tử mảng

hoặc trong khu vực như phương thức lớp. Khi được đặt vào biến địa phương hoặc các

toán hạng stack thì các biến kiểu byte short hay char cũng được chuyển thành int s.

Page | 20

Page 21: Tìm hiểu về jvm

Tìm hiểu JVM

Chúng lưu int trên các khung stack sau đó mới chuyển đổi thành byte, short hay char

khi lưu trữ trên heap hoặc phương thức địa phương.

Cũng lưu ý rằng đối tượng được thông qua như là một tham chiếu đến

runClassMethod() trong Java tất cả đối tượng được thông qua như là tham chiếu. Như

tất cả các đối tượng được lưu trữ trên heap, bạn sẽ không bao giờ tìm thấy hình ảnh

của một đối tượng trong các biến địa phương hoặc toán hạng stack, chỉ phản đối tham

chiếu.

Bên cạnh các thông số của một phương thức, trong đó trình biên dịch phải đặt vào

mảng các biến địa phương đầu tiên và để khai báo, trình biên dịch Java có thể sắp xếp

các mảng các biến đia phương như họ muốn. Trình biên dịch có thể đặt các biến cục

bộ của phương thức vào mảng theo thứ tự nào và họ có thể sử dụng các mục cùng một

mảng cho nhiều hơn một biến địa phương.

Như tất cả các khu vực nhớ thời gian chạy khác, các nhà thiết kế có thể sử dụng bất

cứ cấu trúc dữ liệu mà họ cho là thích hợp nhất để đại diện cho biến địa phương. Các

đặc điểm kỹ thuật của máy ảo Java không sử dụng cho kiểu long và kiểu double nên

được chia trên hai mục mà mảng chiếm đóng. Sử dụng 64bit để lưu trữ 2 kiểu này.

c) Toán hạng stack

Giống như các biến địa phương các toán hạng stack được tổ chức giống như một

mảng các từ. Nhưng không giống các biến địa phương được truy cập thông qua chỉ số

của mảng, các toán hạng stack được truy cập bằng cách push và pop các giá trị. Nếu

một lệnh là push một giá trị vào các toán hạng stack một thời gian sau có thể lấy và sử

dụng giá trị đó.

Các máy ảo lưu trữ cùng loại dữ liệu trong ngăn xếp mà nó lưu trữ các biến địa

phương: int, long, float, double, reference và kiểu biến trả về (return type). Nó chuyển

các giá trị kiểu byte, short, char thành kiểu int trước khi đưa vào toán hạng stack.

Khác với các chương trình truy cập, không được truy cập trực tiếp bởi các chỉ thị

các máy ảo Java không có thanh ghi. Các máy ảo là một stack hơn là một thanh ghi bởi

vì nó lấy các toán hạng từ stack chứ không phải từ thanh ghi. Hàm cũng có thể lấy toán

Page | 21

Page 22: Tìm hiểu về jvm

Tìm hiểu JVM

hạng từ những nơi khác, chẳng hạn như ngay lập tức sau opcode trong dòng bytecode.

Các máy ảo Java tập trung vào các tập lệnh nhưng là các toán tử stack.

Các máy ảo Java sử dụng ngăn xếp toán hạng như một không gian làm việc. Các

hàm pop các giá trị từ toán hạng stack hoạt động trên chúng và push các kết quả.

Trong hình 2.8 bạn có thể thấy được sự miêu tả hoạt động các biến địa phương và

stack khi thực hiện hàm.

Hình 2.8 Mô phỏng việc thêm 2 biến cục bộ

d) Các triển khai có thể có của Stack

Nhà thiết kế có thể thiết kế Stack Java bất cứ như thế nào mà họ muốn. Như đã nói

từ trước, một cách thực hiện các stack là bằng cách phân bổ mỗi khung hình riêng biệt

từ heap.

Ví Dụ:

Page | 22

Page 23: Tìm hiểu về jvm

Tìm hiểu JVM

class Example3c {

public static void addAndPrint() { double result = addTwoTypes(1, 88.88); System.out.println(result); }

public static double addTwoTypes(int i, double d) { return i + d; }}

Hình sau đây cho thấy ba bức ảnh chụp của stack Java cho một thread để gọi

phương thức addAndPrint (). Trong việc thực hiện của các máy ảo Java bên trong

hình, mỗi khung hình được phân bổ riêng biệt từ heap. Để gọi các phương thức

addTwoTypes() và addAndPrint(). Phương thức đầu tiên push một int 1 và double

88,88 vào toán hạng của stack. Sau đó nó gọi phương thức addTwoTypes()

Hình 2.9 Mô phỏng hoạt động stack qua Ví Dụ

Các hàm để gọi addTwoTypes() dùng để chỉ 1 khung liên tuc. Các máy ảo Java

trong lên các mục và giải quyết nó nếu cần thiết

Hình 2.10 cho thấy stack Java của các máy ảo khác nhau thực hiện các phương

thức tương tự. Thay vì phân bổ mỗi khung hình riêng biệt từ heap, điều này thực hiện Page | 23

Page 24: Tìm hiểu về jvm

Tìm hiểu JVM

phân bổ các khung hình từ một ngăn xếp liền kề nhau. Cách tiếp cận này cho phép

thực hiện ghi đè lên khung của phương thức lân cận. Các phần của phương thức gọi

toán hạng stack chứa các tham số cho các phương thức trở thành cơ sở của các biến địa

phương. Trong ví dụ này addAndPrint() ghi đè addTwoTypes toàn bộ biến địa

phương.

Hình 2.10 Phân bố các khung hình từ ngăn xếp liền kề nhau

Cách tiếp cận này giúp tiết kiệm không gian bộ nhớ vì bộ nhớ tương tự được sử

dụng bởi các phương thức gọi để lưu trữ các thông số như được sử dụng theo phương

pháp viện dẫn để truy cập vào các thông số. Nó giúp tiết kiệm thời gian vì các máy ảo

Java không phải mất thời gian sao chép các giá trị tham số từ một khung hình khác.

Lưu ý rằng ngăn xếp toán hạng của khung hiện tại luôn luôn ở “ top” Stack Java.

Mặc dù điều này có thể được dễ dàng hơn để hình dung trong việc thực hiện bộ nhớ kề

Page | 24

Page 25: Tìm hiểu về jvm

Tìm hiểu JVM

nhau của hình 2.10, đó là sự thật không có vấn đề làm thế nào stack Java được thực

hiện.

e) Native Method Stack()

Ngoài tất cả các lĩnh vực dữ liệu thời gian chạy được xác định bởi các đặc điểm kỹ

thuật máy ảo Java và mô tả trước đây, một ứng dụng Java chạy có thể sử dụng các

vùng dữ liệu khác được tạo ra bởi các phương thức địa phương. Khi một thread gọi

một phương thức địa phương, nó bước vào một thế giới mới, trong đó các cấu trúc và

các hạn chế bảo mật của máy ảo Java không còn cản trở sự tự do của mình. Một

phương thức địa phương có khả năng có thể truy cập vào các lĩnh vực dữ liệu thời

gian chạy của máy ảo (nó phụ thuộc vào giao diện phương thức điak phương), nhưng

cũng có thể làm bất cứ điều gì khác mà nó muốn. Nó có thể sử dụng thanh ghi bên

trong bộ vi xử lý địa phương, cấp phát bộ nhớ trên bất kỳ số lượng của heap địa

phương, hoặc sử dụng bất kỳ loại stack.

Nhà thiết kế thực hiện được tự do quyết định những cơ chế mà họ sẽ sử dụng để

cho phép một ứng dụng Java chạy trên việc thực hiện chúng để gọi các phương thức

địa phương.

Bất kỳ giao diện phương thức địa phương sẽ sử dụng một số loại stack. Khi một

thread gọi một phương thức Java, máy ảo tạo ra một khung mới và đẩy nó vào stack

Java. Khi một thread gọi một phương thức địa phương, tuy nhiên, thread ra sau Stack

Java. Thay vì đẩy một frame mới vào thread của Java stack, các máy ảo Java sẽ chỉ

đơn giản là tự động liên kết đến và trực tiếp gọi phương thức địa phương. Một cách để

nghĩ về nó là máy ảo Java là tự động mở rộng chính nó với mã nguồn gốc. Đó là, nếu

như thực hiện máy ảo Java là chỉ cần gọi đến một phương thức khác trong chính nó

khi chương trình Java chạy.

Nếu nguồn gốc giao diện phương thức của một hành động sử dụng một mô hình C-

liên kết, sau đó ngăn xếp phương thức địa phương là C ngăn xếp. Khi một chương

trình C gọi một hàm C, stack hoạt động theo một cách nhất định. Các tham số cho hàm

được đẩy vào ngăn xếp theo một thứ tự nhất định. Giá trị trả lại được chuyển lại cho

Page | 25

Page 26: Tìm hiểu về jvm

Tìm hiểu JVM

các chức năng cách gọi theo một cách nhất định. Đây có thể là hành vi của các stack

phương thức địa phương trong việc thực hiện điều đó.

Một giao diện thức địa phương sẽ có khả năng (một lần nữa, đó là các nhà thiết kế

để quyết định) có thể gọi lại vào máy ảo Java và gọi một phương thức Java. Trong

trường hợp này, các thread trở thành Native Method Stack và đi vào stack Java.

Hình 2.11 Stack cho một thread khi Java gọi phương thức địa phương

Như mô tả trong hình 2.11, một thread đầu tiên gọi hai phương thức Java, thread

thứ hai vừa gọi một phương thức địa phương. Hành động này gây ra các máy ảo để sử

dụng một Native Method Stack. Trong hình này, các phương thức stack địa phương

được hiển thị như là một số lượng hữu hạn của không gian bộ nhớ kề nhau. Giả sử nó

là một C stack. Các vùng stack sử dụng bởi mỗi chức năng C-liên kết được thể hiện

trong màu xám và bao quanh bởi một đường đứt. Các chức năng C-liên kết đầu tiên,

được gọi như là một phương thức địa phương, gọi một chức năng C-liên kết. Các chức

năng C-liên kết thứ hai gọi một phương thức Java thông qua giao diện phương thức địa

Page | 26

Page 27: Tìm hiểu về jvm

Tìm hiểu JVM

phương. Phương pháp Java này gọi một phương pháp Java, đó là phương thức hiện tại

được hiển thị trong hình vẽ.

Như với các khu vực bộ nhớ thời gian chạy khác, bộ nhớ của họ bị chiếm đóng bởi

heap phương thức địa phương không cần phải có kích thước cố định. Nó có thể mở

rộng và hợp nhất khi cần thiết bởi các ứng dụng đang chạy. Triển khai có thể cho phép

người sử dụng hoặc lập trình để xác định một kích thước ban đầu cho các khu vực

phương pháp, cũng như một kích thước tối đa hoặc tối thiểu.

2.2. The Class Loader

Một máy ảo Java có 2 bộ Class Loader: - Class Loader khởi động và Class Loader

được người dùng định nghĩa. Các Bootstrap Loader Class là một phần của việc thực

hiện máy ảo, và Class Loader người dùng định nghĩa là một phần của ứng dụng Java

chạy. Lớp được nạp bằng Class Loader khác nhau được đặt vào không gian riêng bên

trong máy ảo Java.

Các hệ thống phụ class loader liên quan đến nhiều bộ phận khác của máy ảo Java

và một số các Class từ thư viện java.lang. Ví dụ, Class Loader người dùng xác định

được các đối tượng Java thông thường, mà Class từ java.lang.ClassLoader Các

phương thức của lớp ClassLoader cho phép các ứng dụng Java để truy cập vào class

máy nạp của máy ảo. Ngoài ra, đối với mỗi loại nạp máy ảo, nó tạo ra một thể hiện của

lớp java.lang.Class để đại diện cho loại đó. Giống như tất cả các đối tượng, Class

Loader người dùng xác định và thể hiện của lớp cư trú trên heap. Dữ liệu với nhiều

loại tải nằm trong khu vực phương thức.

2.2.1. Loading, Linking and Initialization

Các hệ thống phụ class loader chịu trách nhiệm nhiều hơn chỉ là định vị và nhập dữ

liệu nhị phân cho các Class. Nó cũng phải xác minh tính đúng đắn của các lớp nhập

khẩu, cấp phát và khởi bộ nhớ cho các biến class, và hỗ trợ trong việc giải quyết các

vấn đề liên quan. Những hoạt động này được thực hiện theo một thứ tự nghiêm ngặt:

Loading: Tìm kiếm và nhập dữ liệu cho kiểu

Linking: Thực hiện xác minh, chuẩn bị và giải quyết

o Mã xác nhận: Bảo đảm tính chính xác của các kiểu biến

Page | 27

Page 28: Tìm hiểu về jvm

Tìm hiểu JVM

o Chuẩn bị: Phân bổ bộ nhớ cho các biến class và khởi tạo các bộ nhớ

có giá trị mặc định.

o Giải quyết: Chuyển các kiểu tham số tới và giải quyết trực tiếp.

Initialization: Mã Java khởi tạo các biến các và cho nó giá trị thích hợp

2.2.2. Bootstrap Loader Class

Java triển khai máy ảo phải có khả năng nhận biết và tải các lớp và giao diện

được lưu trữ trong các tập tin nhị phân mà phù hợp với các định dạng tập tin Class

Java. Một lần thực hiện là nhìn nhận các nhị phân khác bên cạnh các file class, nhưng

nó phải nhận ra các file class.

Mỗi Java thực hiện máy ảo có một bộ bootstrap class loader, mà biết làm thế

nào để tải các lớp tin cậy, bao gồm các Class của các API Java. Các đặc điểm kỹ thuật

máy ảo Java không định nghĩa thế nào là bootstrap loader cần xác định vị trí các class.

Đó là một quyết định đặc tả để các nhà thiết kế thực hiện.

Cho một tên biến đầy đủ, Bootstrap Class Loader phải trong một số cách nỗ lực

để xuất các dữ liệu định nghĩa các loại. Một phương pháp phổ biến được thể hiện

bằng Java thực hiện trong máy ảo 1.1 JDK của Sun trên Windows98. Điều này thực

hiện tìm kiếm một đường dẫn thư mục người dùng định nghĩa được lưu trữ trong một

biến môi trường có tên CLASSPATH. Bootstrap Loader tìm kiếm và xuất theo thứ tự

các thư mục xuất hiện trong CLASSPATH, cho đến khi nó tìm thấy một tập tin với tên

thích hợp: tên đầy đủ của biến đang tìm cộng với ".class". Trừ các kiểu là một phần

của gói tin giấu tên, Bootstrap Loader dự kiến các tập tin được trong một thư mục con

của một thư mục trong classpath. Các tên đường dẫn của thư mục con được xây dựng

từ các tên gói của kiểu. Ví dụ, nếu bootstrap class loader đang tìm cho class

java.lang.Object, nó sẽ tìm Object.class trong java \ lang thư mục con của mỗi

CLASSPATH thư mục.

Trong 1.2, Bootstrap Class Loader của của Sun Java 2 SDK chỉ về trong thư

mục mà trong đó các lớp hệ thống (các file class của Java API) đã được cài đặt. Các

Bootstrap Class Loader của các máy ảo Java từ Sun Java 2 SDK không nhìn vào

CLASSPATH. Trong Java 2 SDK máy ảo của Sun, tìm kiếm đường dẫn class là công Page | 28

Page 29: Tìm hiểu về jvm

Tìm hiểu JVM

việc của các system class loader, một class loader người dùng định nghĩa được tạo ra

tự động khi máy ảo khởi động.

2.2.3. Loader Class người dùng định nghĩa (user-defined class loader)

Mặc dù user-defined class loader được tự bản thân định nghĩa , 4 phương thức

của class ClassLoader như là 4 cổng vào của máy ảo

protected final Class defineClass(String name, byte data[], int offset, int length);protected final Class defineClass(String name, byte data[], int offset, int length, ProtectionDomain protectionDomain);protected final Class findSystemClass(String name);protected final void resolveClass(Class c);

Bất kì máy ảo Java nào phải quan tâm tới việc kết nối các phương thức của

ClassLoader hệ thống tới classloader nội bộ.

Hai phương thức defineClass () phương pháp chấp nhận một byte array, dữ liệu

[], như là đầu vào. Bắt đầu từ vị trí offset trong mảng và tiếp tục cho tới độ dài byte,

lớp ClassLoader hy vọng dữ liệu nhị phân phù hợp với các định dạng tập tin lớp Java -

dữ liệu nhị phân đại diện cho một kiểu mới cho các ứng dụng đang chạy - với tên đầy

đủ quy định trong tên. Các kiểu được gán như là 2 giá trị mặc định, nếu các bản đầu

tiên của defineClass () được sử dụng, hoặc tham chiếu đối tượng bởi

protectionDomain (). Mỗi máy ảo Java phải đảm bảo các phương thức defineClass ()

của lớp ClassLoader có thể tạo ra một dạng mới có thể cho vào khu vực phương thức

Các phương thức findSystemClass () chấp nhận một chuỗi là tên của một kiểu.

Khi Class Loader người dùng định nghĩa gọi phương thức này trong phiên bản 1.0 và

1.1, nó được yêu cầu rằng các máy ảo thử tất cả các loại trên qua bootstrap class. Nếu

Bootstrap Class Loader đã được nạp thành công hay tìm được kiểu, nó sẽ trả về một

tham chiếu đến các lớp đối tượng đại diện cho kiểu. Nếu nó không thể xác định vị trí

các dữ liệu nhị phân cho kiể, nó ném một ngoại lệ ClassNotFoundException. Trong

phiên bản 1.2, các phương thức findSystemClass () cố gắng tìm đúng yêu cầu từ hệ

thống. Mỗi máy ảo Java phải đảm bảo các phương thức findSystemClass ( ) có thể gọi

Page | 29

Page 30: Tìm hiểu về jvm

Tìm hiểu JVM

bootstrap (nếu phiên bản 1.0 hoặc 1.1) hoặc hệ thống (nếu phiên bản 1.2 hoặc mới

hơn) class loader theo cách này.

Các resolveClass () phương pháp chấp nhận một tham chiếu đến một biến thuộc

dạng class. Phương pháp này gây ra các đại diện lớp để được liên kết (nếu nó chưa

được liên kết). Các defineClass () phương pháp, mô tả trước đây, chỉ chăm lo công

việc tìm kiếm. Khi defineClass () trả về đối tượng lớp , các tập tin nhị phân cho các

kiểu đã chắc chắn được đặt và nhập khẩu vào khu vực phương thức, nhưng không nhất

thiết liên kết và khởi tạo. Máy ảo Java chắc chắn rằng triển khai các phương thức

resolveClass () của class ClassLoader có thể gây ra các hệ thống phụ class loader để

thực hiện kết nối.

2.2.4. Name Spaces

Mỗi Class Loader duy trì không gian cư trú riêng của các loại nó đã được nạp.

Bởi vì mỗi Class Loader có không gian riêng của mình, một ứng dụng Java đơn lẻ có

thể nạp nhiều loại với cùng tên. Tên đầy đủ của kiểu, do đó, không phải lúc nào cũng

đủ để nhận diện nó bên trong một máy ảo Java. Nếu nhiều loại cùng tên đã được nạp

vào không gian tên khác nhau, danh tính của bộ nạp lớp đó nạp các kiểu (danh tính của

không gian tên nó là bên trong) cũng sẽ là cần thiết để nhận diện kiểu đó.

Không gian tên phát sinh bên trong một máy ảo Java ví dụ như là kết quả của

quá trình phân giải. Là một phần của dữ liệu cho từng kiểu, các máy ảo Java theo dõi

các Class Loader khi nạp các kiểu. Khi máy ảo cần phải giải quyết một tham chiếu từ

một class khác, nó yêu cầu các class được tham chiếu từ các Class Loader tham chiếu

giống vậy.

2.3. Các Kiểu Dữ Liệu

Các máy ảo Java tính bằng cách thực hiện các hoạt động trên một số loại dữ

liệu. Cả hai loại dữ liệu và các hoạt động được quy định chặt chẽ bởi các đặc điểm kỹ

thuật máy ảo Java. Các kiểu dữ liệu có thể được chia thành một tập hợp của các loại

nguyên thủy và một kiểu tham chiếu. Biến của các loại nguyên thủy giữ giá trị nguyên

thủy, và các biến của các loại tham chiếu giữ giá trị tham chiếu. Giá trị tham chiếu là

tham chiếu đối tượng, nhưng không phải là đối tượng chính mình. Giá trị nguyên thủy,

ngược lại, không đề cập đến bất cứ điều gì. Chúng là những dữ liệu thực tếc của

Page | 30

Page 31: Tìm hiểu về jvm

Tìm hiểu JVM

chúng. Bạn có thể thấy một sự miêu tả đồ họa của gia đình các máy ảo Java của kiểu

dữ liệu trong hình 2.12.

Hình 2.12 Các kiểu dữ liệu trong Java

Tất cả các kiểu nguyên thủy của ngôn ngữ lập trình Java là các kiểu nguyên

thủy của các máy ảo Java. Mặc dù boolean đủ tiêu chuẩn là một kiểu nguyên thủy của

các máy ảo Java, hướng dẫn thiết lập đã hỗ trợ rất hạn chế cho nó. Khi một trình biên

dịch mã nguồn Java vào bytecode, nó sử dụng int s hoặc byte s để đại diện cho boolean

s. Trong các máy ảo Java, false được đại diện bởi số nguyên không và true đại diện

bởi bất kỳ số nguyên nào khác không. Hoạt động liên quan đến boolean giá trị sử dụng

int s. Mảng của boolean được truy cập như mảng của byte, mặc dù chúng có thể được

biểu diễn trên heap như mảng của byte hoặc như các bit.

Page | 31

Page 32: Tìm hiểu về jvm

Tìm hiểu JVM

Các loại nguyên thủy của ngôn ngữ lập trình Java khác hơn boolean dạng các

kiểu dữ liệu của các máy ảo Java. Các kiểu dữ liệu được chia sẻ giữa các loại tách rời:

byte, short, int, long, và char, và floating-point: float và double. Cũng như với các

ngôn ngữ lập trình Java, các loại nguyên thủy của các máy ảo Java có dải khắp mọi

nơi. Dạng long trong máy ảo Java luôn thực hiện như một số bù hai 64bit, độc lập với

các nền tảng máy chủ cơ bản.

Các máy ảo Java làm việc với một loại nguyên thủy khác là không có sẵn cho

các lập trình viên Java: các returnAddress loại. Loại nguyên thủy này được sử dụng để

thực hiện cuối cùng các điều khoản của chương trình Java.

Các kiểu tham số của máy ảo Java được đặt tên như tham biến. Giá trị của các

kiểu tham chiếu có 3 kiểu: dạng class, dạng interface, và dạng mảng array. Tất cả ba

loại đều có những giá trị mà là tham chiếu cho các đối tượng. Giá trị dạng class là

tham chiếu cho các class. Giá trị kiểu mảng của chiếu cho các mảng, mà là các đối

tượng chính thức trong các máy ảo Java. Giá trị dạng interface tham chiếu cho các lớp

mà thực hiện một giao diện. Một giá trị tham chiếu khác là không có giá trị, mà chỉ ra

các tham chiếu biến không đề cập đến bất kỳ đối tượng nào.

Các đặc điểm kỹ thuật máy ảo Java xác định phạm vi của các giá trị cho mỗi

loại dữ liệu, nhưng không xác định kích thước của chúng. Số lượng các bit được sử

dụng để lưu trữ giá trị của từng loại dữ liệu là một quyết định của các nhà thiết kế của

việc triển khai cá nhân. Các phạm vi của các kiểu dữ liệu của máy ảo Java được thể

hiện trong Bảng 2.1

Kiểu Phạm vi

Byte 8-bit đã ký hai của số nguyên bù (-2 7 để 2 7 - 1, bao gồm)

ngắn 16-bit đã ký hai của số nguyên bù (-2 15 để 2 15 - 1, bao gồm)

Int 32-bit đã ký hai của số nguyên bù (-2 31 để 2 31 - 1, bao gồm)

Dài 64-bit đã ký hai của số nguyên bù (-2 63 để 2 63 - 1, bao gồm)

char 16-bit ký tự Unicode không dấu (0-2 16 - 1, bao gồm)

phao 32-bit IEEE 754 chính xác đơn float

gấp đôi 64-bit IEEE 754 chính xác đôi nổiPage | 32

Page 33: Tìm hiểu về jvm

Tìm hiểu JVM

returnAddress địa chỉ của một opcode trong cùng một phương pháp

tham chiếu tham chiếu đến một đối tượng trên heap, hoặc rỗng

Bảng 2.1 Phạm vi các kiểu dữ liệu trong máy ảo Java

2.4. Word Size

Các đơn vị cơ bản của kích thước cho các giá trị dữ liệu trong máy ảo Java là từ

--a kích thước cố định được lựa chọn bởi các nhà thiết kế của mỗi Java thực hiện máy

ảo. Các kích thước Word phải đủ lớn để chứa một giá trị kiểu byte, ngắn, int, char,

float, returnAddress, hoặc tham chiếu. Hai từ phải đủ lớn để chứa một giá trị kiểu long

và double. Do đó một nhà thiết kế thực hiện phải chọn một cỡ chữ mà ít nhất là 32 bit,

nhưng nếu không có thể chọn bất cứ điều gì từ kích thước sẽ mang lại việc thực hiện

hiệu quả nhất. Các kích thước từ thường được chọn để được kích thước của một con

trỏ bản địa trên nền tảng máy chủ.

Các đặc điểm kỹ thuật của nhiều vùng dữ liệu thời gian chạy của máy ảo Java là

dựa trên các khái niệm trừu tượng này của một từ. Ví dụ, hai phần của một stack frame

Java - các biến địa phương và toán hạng stack-- được quy định trong các điều khoản

của các từ. Các khu vực này có thể chứa các giá trị của bất kỳ loại dữ liệu của máy ảo.

Khi được đặt vào các biến địa phương hoặc toán hạng stack, một giá trị chiếm một

hoặc hai từ.

Khi họ chạy, chương trình Java không thể xác định kích thước chữ của máy chủ

thực hiện máy ảo của họ. Các kích thước từ không ảnh hưởng đến hành vi của một

chương trình. Nó chỉ là một thuộc tính nội bộ của một máy ảo thực hiện.

2.5. Program Counter

Mỗi thread của một chương trình đang chạy có riêng register pc, hoặc truy cập

chương trình của nó, được tạo ra khi các thread được bắt đầu. Sổ register pc là một từ

trong kích thước, vì vậy nó có thể giữ cả một con trỏ bản địa và một returnAddress.

Như một thread thực thi một phương thức Java, register pc chứa địa chỉ của các hướng

dẫn hiện đang được thực thi bởi các sợi. Một "địa chỉ" có thể là một con trỏ bản địa

Page | 33

Page 34: Tìm hiểu về jvm

Tìm hiểu JVM

hoặc một offcode từ đầu bytecode của một phương thức Nếu một thread đang thực thi

một phương thức có nguồn gốc, giá trị của thanh ghi pc là không xác định.

2.6. Threads (luồng trong Java)

Các đặc điểm kỹ thuật máy ảo Java định nghĩa một mô hình luồng nhằm tạo

thuận lợi cho việc thực hiện trên một loạt các kiến trúc. Một mục tiêu của mô hình

luồng Java là cho phép các nhà thiết kế thực hiện, nếu có thể và thích hợp, sử dụng.

Ngoài ra, các nhà thiết kế có thể thực hiện một cơ chế luồng như là một phần của việc

thực hiện máy ảo của họ. Một ưu điểm của việc sử dụng luồng trên một máy chủ đa xử

lý là luồng khác nhau của một ứng dụng Java có thể chạy đồng thời trên bộ vi xử lý

khác nhau.

Một sự đánh đổi của mô hình luồng của Java là đặc điểm kỹ thuật của các ưu

tiên là mẫu số thấp nhất common-. Một luồng Java có thể chạy ở bất kỳ một trong

mười ưu tiên. Ưu tiên một là thấp nhất, và mười ưu tiên cao nhất. Nếu các nhà thiết kế

sử dụng luồng địa phương, họ có thể bản đồ mười ưu tiên Java vào các ưu tiên địa

phương có vẻ thích hợp nhất. Các đặc điểm kỹ thuật máy ảo Java định nghĩa hành vi

của luồng tại các ưu tiên khác nhau chỉ bằng cách nói rằng tất cả các luồng ở mức ưu

tiên cao nhất sẽ nhận được một số thời gian CPU. Luồng tại ưu tiên thấp hơn được

đảm bảo để có được thời gian CPU chỉ khi tất cả luồng đề ưu tiên cao hơn đều bị chặn.

Đề ưu tiên thấp hơn có thể nhận được một số thời gian CPU khi đề ưu tiên cao hơn

không bị chặn, nhưng không có bảo đảm.

Các đặc điểm kỹ thuật không thừa thời gian cắt giữa các luồng ưu tiên khác

nhau, bởi vì không phải tất cả các kiến trúc thời gian-slice. (Như được sử dụng ở đây,

thời gian cắt nghĩa rằng tất cả các luông ở tất cả các ưu tiên sẽ được đảm bảo một số

CPU thời gian, ngay cả khi không có luồng bị chặn.) Ngay cả trong số những kiến trúc

đó làm thời gian-slice, các thuật toán được sử dụng để phân bổ khe thời gian để luồng

tại ưu tiên khác nhau có thể khác nhau rất nhiều.

Trong các máy ảo Java Specification, hành vi của luông Java được định nghĩa

theo các biến, một bộ nhớ chính, và trạng thái làm việc cũ. Mỗi máy ảo Java có một bộ

nhớ chính, trong đó có chứa tất cả các biến của chương trình: các biến thể hiện của các

đối tượng, các thành phần của mảng, và các biến Class. Mỗi thread có một trạng thái

Page | 34

Page 35: Tìm hiểu về jvm

Tìm hiểu JVM

làm việc cũ. Biến và các tham số địa phương, bởi vì họ tin vào các luồng cá nhân,

logic có thể được xem như là một phần của một trong hai bộ nhớ làm việc hoặc bộ nhớ

chính.

Các đặc điểm kỹ thuật máy ảo Java định nghĩa nhiều quy tắc chi phối các mối

tương tác ở mức độ thấp của luồng với bộ nhớ chính. Ví dụ, một quy tắc rằng tất cả

các hoạt động trên các kiểu nguyên thủy, ngoại trừ trong một số trường hợp long s và

double s, là nguyên tử. Ví dụ, nếu hai luồng cạnh tranh để viết hai giá trị khác nhau về

một biến int , ngay cả trong trường hợp không đồng bộ, biến sẽ kết thúc với một giá trị

sai khác. Biến đó sẽ không có một giá trị bị lỗi. Nói cách khác, một trong những luồng

sẽ giành chiến thắng trong cạnh tranh và viết giá trị của nó để biến đầu tiên. Các luông

thua không cần phải phiền muộn, tuy nhiên, vì nó sẽ viết giá trị của nó vào biến thứ

hai, ghi đè lên biến của luồng “chiến thắng”.

Về cơ bản, các quy định về hành vi thread-mức thấp chỉ định khi một luồng có

thể và khi đó phải:

1. Sao chép các giá trị của các biến từ bộ nhớ chính để bộ nhớ làm việc của

mình.

2. Viết các giá trị từ bộ nhớ làm việc của mình trở lại vào bộ nhớ chính.

Đối với điều kiện nhất định, các quy tắc xác định một thứ tự chính xác và dự

đoán được bộ nhớ đọc và viết. Đối với các điều kiện khác, tuy nhiên, các quy tắc

không chỉ định bất kỳ trật tự. Các quy tắc được thiết kế để cho phép lập trình Java để

xây dựng các chương trình đa luồng mà biểu hiện hành vi dự đoán, trong khi cho các

nhà thiết kế thực hiện một cách linh hoạt. Sự linh hoạt này cho phép các nhà thiết kế

của Java triển khai máy ảo để tận dụng lợi thế của phần cứng và phần mềm tiêu chuẩn

kỹ thuật có thể cải thiện hiệu suất của các ứng dụng đa luồng.

Các cấp cao ý nghĩa cơ bản của tất cả các quy tắc ở mức độ thấp chi phối hành

vi của đề tài này là: Nếu truy cập vào các biến nhất định không đồng bộ, luồng được

phép cập nhật các biến trong bộ nhớ chính trong bất kỳ thứ tự. Nếu không đồng bộ,

các ứng dụng đa luồng của bạn có thể thể hiện hành vi đáng ngạc nhiên về một số việc

triển khai máy ảo Java. Với việc sử dụng hợp đồng bộ, tuy nhiên, bạn có thể tạo ra các

Page | 35

Page 36: Tìm hiểu về jvm

Tìm hiểu JVM

ứng dụng đa luồng Java mà cư xử một cách dự đoán về bất kỳ thực hiện của các máy

ảo Java.

2.7. Native Method Interface

Java triển khai máy ảo không cần thiết để hỗ trợ bất kỳ native method interface

đặc biệt. Triển khai một số có thể hỗ trợ không có native method interface ở tất cả.

Người khác có thể hỗ trợ một số, mỗi hướng với một mục đích khác nhau.

Java Native Interface của Sun, hoặc JNI, là hướng tới tính di động. JNI được

thiết kế để nó có thể được hỗ trợ bởi bất kỳ thực hiện của máy ảo Java, không có vấn

đề gì kỹ thuật thu gom rác thải hoặc đại diện đối tượng thực hiện sử dụng. Điều này sẽ

cho phép các nhà phát triển để liên kết cùng (JNI tương thích) binaries phương thức có

nguồn gốc từ bất kỳ JNI-hỗ trợ triển khai máy ảo trên một nền tảng máy chủ cụ thể.

Nhà thiết kế thực hiện có thể chọn để tạo ra các phương thức giao diện địa

phương độc quyền, thêm vào, hoặc thay thế, JNI. Để đạt được tính di động của nó, là

JNI sử dụng rất nhiều về con trỏ và hàm con trỏ đến các chức năng. Để có được hiệu

quả tuyệt đỉnh, các nhà thiết kế của một thực hiện có thể quyết định cung phương thức

giao diện địa phương ở mức độ thấp của riêng mình mà vẫn gắn chặt với các cơ cấu

thực hiện cụ thể của mình. Nhà thiết kế cũng có thể quyết định cung cấp một native

method interface cấp cao hơn JNI, chẳng hạn như một trong đó sẽ đem lại các đối

tượng Java thành một mô hình thành phần phần mềm.

Để làm việc hữu ích, một native method interface có khả năng tương tác ở mức

độ nào với các trạng thái nội bộ của máy ảo Java. Ví dụ, một native method interface

có thể cho phép các phương thức địa phương làm một số hoặc tất cả những điều sau

đây:

Duyệt và trả về dữ liệu (pass and return data)

Truy cập hoặc gọi các phương thức thu gom các đối tượng trên Heap

Biến class Access hoặc gọi phương thức class

Truy cập vào các mảng

Khoá một đối tượng trên Heap để sử dụng cho luồng hiện tại

Tạo một đối tượng mới trên Heap

Page | 36

Page 37: Tìm hiểu về jvm

Tìm hiểu JVM

Nạp các class mới

Ném ra ngoại lệ

Ném ngoại lệ được gọi bởi phương thức

Bắt ngoại lệ không đồng bộ và ném ra bởi máy ảo

Dọn dẹp các đối tượng mà không còn được sử dụng trên Heap

Thiết kế một Native Method Interface mà cung cấp các dịch vụ này có thể phức

tạp. Các thiết kế cần phải đảm bảo rằng các bộ thu rác không giải phóng bất kỳ đối

tượng đang được sử dụng bởi các phương thức địa phương. Nếu thu gom rác của một

thực hiện di chuyển các đối tượng để giữ cho heap phân mảnh ở mức tối thiểu, thiết kế

phương thức giao diện phải đảm bảo rằng một trong hai:

- Một đối tượng có thể được di chuyển sau khi tham chiếu của nó đã được

thông qua với một phương pháp bản địa.

- Bất kỳ đối tượng có tham chiếu đã được thông qua với một phương thức địa

phương được gắn cho đến khi trở về phương thức địa phương hoặc nếu

không biết nó được thực hiện với các đối tượng

.

Page | 37

Page 38: Tìm hiểu về jvm

Tìm hiểu JVM

TÀI LIỆU THAM KHẢO

[1] https://vncoding.wordpress.com/2016/03/30/cung-tim-hieu-ve-jvm/

[2] https://en.wikipedia.org/wiki/Java_virtual_machine

[3] http://daynhauhoc.com/t/java-virtual-machine-va-c-ch-ho-t-d-ng/15082

[4] INSIDE THE JAVA VIRTUAL MACHINE - Bill Venners.

Page | 38