Tìm hiểu về jvm (java virtual machine)
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
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
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………………………………….….…......7
Page | 3
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
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
Page | 5
Tìm hiểu JVM
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.
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 TimeJIT". 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.
Page | 6
Tìm hiểu JVM
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
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
Page | 7
Tìm hiểu JVM
Như trong hình ta thấy Java có 3 thành phần chính
1.
2.
3.
Class Loader: Tìm kiếm và nạp các file.class vào vùng nhớ java
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
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.
Page | 8
Tìm hiểu JVM
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.
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.
Page | 9
Tìm hiểu JVM
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
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
Page | 10
Tìm hiểu JVM
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.
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
Page | 11
Tìm hiểu 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.
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ó.
Page | 12
Tìm hiểu JVM
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
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
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
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
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.
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
Page | 16
Tìm hiểu JVM
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
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à
Page | 17
Tìm hiểu JVM
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
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
Page | 18
Tìm hiểu JVM
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
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
- Xem thêm -