Professional Documents
Culture Documents
HÀ NỘI 2007
MỤC LỤC
MỤC LỤC.............................................................................................................................ii
JAVA VIRTUAL MACHINE................................................................................................1
(Máy Ảo Java).......................................................................................................................1
12.1 Thế nào là máy ảo Java............................................................ ...................1
12.1.1 Thời gian sống của máy ảo Java............................................. .................1
12.2 Kiến trúc trong máy ảo java............................................... ........................2
12.2.1 Các kiểu dữ liệu............................................................ ............................5
12.2.2 Kích thước của từ......................................................... ............................6
12.2.3 Class Loader subsystem............................................... ............................7
12.2.4 Vùng phương thức (Method area).............................................. .............9
12.2.5 Bộ nhớ Heap.............................................................................. ..............11
12.2.6 Garbage Collection............................................................. ....................12
12.2.7 Ngăn xếp Java...................................................................... ...................18
12.2.7.1 Stack frame................................................................................................................................19
12.2.7.2 Ngăn xếp toán hạng...................................................................................................................21
12.2.7.3 Frame data.................................................................................................................................21
12.2.7.4 Ngăn xếp phương thức cơ sở....................................................................................................25
(Máy Ảo Java)
Đặc tả trừu tượng nói rõ những thành phần, chức năng mà một máy ảo Java
cần có. Một cài đặt là dựa trên các đặc tả trừu tượng đó thì các hãng khác nhau tạo
ra các cài đặt khác nhau cho máy ảo Java . Còn một thể hiện chỉ có khi một ứng
dụng Java chạy.
Một ứng dụng Java chạy bên trong một thể hiện của một cài đặt cụ thể của một
đặc tả trừu tượng của máy ảo Java. Thuật ngữ JVM trong tài liệu này dùng để chỉ cả
3 ý nghĩa này.
}
Hàm main() trong lớp khởi tạo có vai trò như là điểm bắt đầu của luồng khởi
tạo ứng dụng. Luồng khởi tạo ứng dụng có thể sinh ra hoặc kết thúc những luồng
khác.
Trong JVM thì các luồng được phân chia thành 2 loại là daemon( hậu cảnh) và
non-daemon. Một tiến trình daemon là một luồng thông thường được sử dụng bởi
chính máy ảo JVM như luồng thực thi dọn dẹp bộ nhớ. Ứng dụng có thể đánh dấu
bất kì luồng nào mà nó tạo ra là luồng daemon. Luồng khởi đầu của ứng dụng là
luồng non-daemon.
Một ứng dụng java tiếp tục thực thi( một cài đặt của máy ảo java vẫn tiếp tục
tồn tại) khi mà bất kì một luồng non-daemon nào vẫn chạy.
Khi mà tất cả các luồng non-daemon của ứng dụng Java kết thúc thì cài đặt
của máy ảo Java sẽ kết thúc theo. Chương trình cũng sẽ kết thúc nếu nó gọi hàm
exit() của lớp Runtime hoặc lớp System.
Một số vùng nhớ dữ liệu thời gian chạy được chia sẻ giữa các tiến trình của
ứng dụng, trong khi một số khác lại của riêng một số tiến trình. Mỗi thể hiện của
máy ảo java có một vùng dành cho các phương thức và một bộ nhớ heap. Những
vùng nhớ này được chia sẻ giữa các tiến trình chạy bên trong máy ảo. Khi máy ảo
Hình 12-2: Vùng dữ liệu thời gian chạy chia sẻ trong tất cả các luồng
tải một file lớp, nó phân tích thông tin một kiểu từ dữ liệu nhị phân chứa trong file
lớp và sau đó chuyển thông tin kiểu này vào trong vùng method area. Khi một
chương trình chạy thì máy ảo chuyển tất cả các đối tượng mà chương trình sinh ra
vào trong bộ nhớ heap.
Khi một luồng mới được tạo ra thì nó sẽ nhận một thanh ghi PC của chính nó
và một ngăn xếp Java. Nếu luồng này thực thi một phương thức java (không phải
một phương thức nguyên thuỷ) thì giá trị của thanh ghi PC sẽ chứa chỉ thị tiếp theo
để thực thi. Ngăn xếp Java chứa trạng thái của lời gọi phương thức java (không phải
lời gọi nguyên thuỷ) cho luồng đó. Lời gọi phương thức java bao gồm biến cục bộ
của nó, các tham số mà nó được gọi, giá trị trả về (nếu có) và kết quả tính toán trung
gian. Trạng thái của lời gọi phương thức nguyên thuỷ được chứa trong một ngăn
xếp phương thức nguyên thuỷ, giống như trong một thanh ghi hay trong một vùng
nhớ thực thi phụ thuộc.
Ngăn xếp Java được tạo nên bởi các stack frame (hay còn gọi là frame). Một
frame chứa trạng thái của một lời gọi hàm. Khi một luồng gọi một phương thức thì
máy ảo java sẽ đẩy (push) một frame mới vào trong ngăn xếp, và khi mà phương
thức hoàn thành thì máy ảo sẽ lấy và loại bỏ frame này ra.
Máy ảo java không có thanh ghi nào để chứa giá trị trung gian. Tập chỉ thị sử
dụng ngăn xếp java để chứa giá trị trung gian. Cách tiếp cận này được người thiết
kế tạo nên để giữ cho tập chỉ thị của máy ảo java được chặt chẽ rõ ràng và làm
thuận tiện cho việc thực thi trên kiến trúc với một vài hoặc các thanh ghi không có
mục đích thông thường. Ngoài ra thì kiến trúc dựa trên ngăn xếp của tập chỉ thị của
máy ảo java làm thuận tiện cho việc tối ưu mã làm việc được thực hiện bởi trình
biên dịch động và thời gian thực ( trình biên dịch này làm việc trong một số thực thi
của máy ảo java ).
double. Do đó kích thước nhỏ nhất của từ là 32 bit. Nhưng thông thường nó được
chọn bằng kích thước của con trỏ nguyên thuỷ trên nền tảng máy chủ.
Đặc tả của nhiều vùng dữ liệu thời gian chạy của nhiều máy ảo java dựa trên
khái niệm trừu tượng của từ. Ví dụ hai đoạn của Java stack frame là biến cục bộ và
toán hạng được định nghĩa dựa trên thuật ngữ word. Những khu vực này có thể
chứa nhiều giá trị của bất kì kiểu dữ liệu nào của máy ảo java. Khi chúng được
chuyển vào vùng biến cục bộ và vùng toán hạng thì giá trị này sẽ chiếm một hoặc 2
từ.
Khi chạy thì chương trình Java không thể biết được kích thước của từ ( phụ
thuộc nền tảng bên dưới) nhưng kích thước này không ảnh hưởng đến hành vi của
chương trình.
Mặc dù UCL bản thân nó là một phần của ứng dụng Java, nhưng 4 phương
thức sau trong lớp ClassLoader là cửa ngõ để vào JVM.
ClassLoader:
− Protected final Class defineClass( String name,byte data[], int offset,
int length);
− Protected final Class defineClass(String name, byte data[], int offset,
int length, ProtectionDemain protectionDomain);
− Protected final Class findSystemClass( String name);
Hai hàm đầu tiên định nghĩa lớp dựa vào các tham số như tên lớp, mảng dữ
liệu nhị phân, độ dịch (offset) và độ dài dữ liệu. Phương thức tiếp theo đưa ra thông
tin về lớp từ tên đầy đủ của lớp. Phương thức cuối cùng giúp JVM thực hiện liên kết
đến một lớp.
− Full quatified name của lớp cha trực tiếp của nó ( trừ kiểu
java.lang.Object vì nó không có lớp cha)
− Kiểu này là lớp hay giao diện
− Danh sách có thứ tự của fully quatified name của bất kì giao diện trực
tiếp bên trên.
Bên trong file lớp và JVM thì tên của kiểu được chứa dưới dạng tên đầy đủ.
Trong mã nguồn thì tên đầy đủ có dạng tengoi.tenlop ví dụ java.lang.object. Còn
trong file lớp thì là java/lang/object. Đối với vùng methor area thì tên đầy đủ có thể
được thể hiện ở dạng form hoặc cấu trúc dữ liệu, tuỳ vào người thiết kế.
Ngoài các thông tin kể trên thì máy ảo còn phải chứa các thông tin sau cho
mỗi kiểu:
Danh sách các đối tượng dùng chung ( constant pool). Nó là một tập các hằng
được kiểu này sử dụng như String, integer,… và các tham chiếu đến các kiểu khác,
và các phương thức được sử dụng bởi kiểu này.
Thông tin về các trường bên trong. Các trường này cũng chứa trong vùng
methor area. Khai báo về thứ tự các trường này cũng phải được ghi lại. Thông tin về
mỗi trường bao gồm: tên trường, tên kiểu, bổ từ của trường ( public, private,
protected,..)
Thông tin về các phương thức. Giống như thông tin về các trường, nó cũng
bao gồm: tên phương thức, giá trị trả về, bổ từ của phương thức. Với mỗi phương
thức không phải là phương thức trừu tượng thì còn có thêm các thông tin: mã
bytecode của phương thức, cỡ của ngăn xếp toán hạng, và mục biến cục bộ của
stack frame của phương thức, bảng ngoại lệ.
Các biến của lớp được chia sẻ giữa tất cả các đối tượng của một lớp, nó kết
hợp với lớp chứ không phải là với một thể hiện của lớp. Vì thế một cách logic nó là
một phần của dữ liệu lớp và dĩ nhiên được chứa trong vùng methor area. Trước khi
JVM sử dụng một lớp thì nó phải cấp phát bộ nhớ cho mỗi biến của lớp, ngoại trừ
hằng biên dịch thời gian ( là biến của lớp được khai báo là final và giá trị chỉ được
xác định tại thời điểm biên dịch).
Một tham chiếu đến lớp ClassLoader. Với mỗi kiểu mà nó tải thì JVM phải
giữ liên hệ với kiểu đã được tải bởi bootstrap class loader hoặc user-define class
loader. Cho những kiểu được tải bởi user-defined class loader thì JVM phải chứa
một tham chiếu đến user-defined class loader mà đã tải kiếu đấy. Thông tin này
được chứa như là một phần của dữ liệu của kiếu trong vùng methor area. Máy ảo sử
dụng thông tin này trong suốt quá trình liên kết động. Khi một kiểu tham chiếu đến
một kiểu khác thì máy ảo sẽ yêu cầu kiểu được tham chiếu từ cùng một bộ tải lớp đã
tải kiểu đang tham chiếu. Kiểu sử lý này của liên kết động cũng là trung tâm của
cách thức mà máy ảo java hình thành nên các không gian tên riêng biệt. Để thực thi
một cách đúng đắn liên kết động và duy trì nhiều không gian tên khác nhau máy ảo
cần biết bộ tải lớp tưong ứng với mỗi kiểu trong vùng methor area. Chi tiết của liên
kết động và không gian tên được thảo luận chi tiết trong chương 8, “ Mô hình liên
kết”.
Một tham chiếu đến lớp Class ( java.lang.Class). một thể hiện của lớp
java.lang.Class được tạo bởi máy ảo java cho mỗi kiểu mà nó tải. JVM phải liên kết
một tham chiếu đến một thể hiện của lớp Class cho mỗi kiểu.
Bảng phương thức
Thông tin về kiểu phải được tổ chức bên trong methor area để có thể truy cập
được một cách nhanh chóng. Ngoài ra để tinh chế các thông tin đã nêu trước đây thì
các sự thực thi phải bao gồm cấu trúc dữ liệu khác mà có thể đẩy nhanh việc truy
cập đến dữ liệu cần tinh chế. Một ví dụ về cấu trúc dữ liệu kiểu này là bảng phương
thức. Với mỗi lớp không trừu tượng mà JVM tải thì nó có thể sinh một bảng
phương thức và bao gồm nó giống như là một phần của thông tin lớp được chứa
trong vùng methor area. Một bảng phương thức là một mảng của tham chiếu trực
tiếp đến tất cả các phương thức thể hiện mà có thể được gọi trong một thể hiện của
một lớp, bao gồm cả các phương thức thừa kế từ lớp cha. Một bảng phương thức
cho phép máy ảo Java nhanh chóng định vị một phương thức thể hiện được gọi trên
một đối tượng.
dữa liệu vùng Heap. Tuy nhiên, hai luồng khác nhau của cùng1 ứng dụng, có thể
gây tác hại đối với vùng dữ liệu heap của luồng kia. Đây là tại sao mà bạn phải lo
lắng về sự đồng bộ hóa thích hợp truy cập đa luồng tới các đối tượng(dữ liệu bộ nhớ
Heap) trong chương trình java của bạn.
Máy ảo java có một chỉ lệnh mà cấp phát bộ nhớ trong vùng nhớ heap cho
một đối tượng mới, nhưng mà không có chỉ lệnh giải phóng cùng nhó đó. Đúng như
bạn không thể chỉ rõ việc giải phóng đối tượng trong mã nguồn Java và giải phóng
đối tượng trong Java bytecodes. Chính máy ảo chịu trách nhiệm quyết định có hay
không và khi nào giải phóng bộ nhớ bị chiếm bởi các đối tượng mà không còn liên
quan đến ứng dụng đang chạy. Thông thường sự thi hành bằng máy ảo java sử dụng
một bộ thu dọn giác để quản lý vùng heap.
nhớ heap của nó. Nói cách khác khi máy ảo cần bộ nhó cho một lớp được nạp mới,
nó có thể lấy bộ nhớ từ cùng một heap mà trên đó các đối tượng đang cư chú. Cùng
bộ thu dọn rác mà giải phóng bộ nhớ đang bị chiếm giữ bởi những đối tượng không
còn liên quan có thể chú ý tới kết quả tìm kiếm và giải phóng những lớp không còn
liên quan nữa. Các cài đặt có thể cho phép những người sử dụng hoặc lập trình viên
chỉ định một kích thước ban đầu cho bộ nhớ heap, cũng như một kích thước tối đa
và tối thiểu.
Object Representation(Mô tả đối tượng)
Đặc tả máy ảo java ít đề cập cách làm thế nào các đối tượng thể hiện trên
heap. Mô tả đối tượng- một khía cạnh phân tích của toàn bộ thiết kế của heap và thu
hồi bộ nhơ- là quyết định của người thiết kế thực thi.
Dữ liệu chính mà trong cách thể hiện của mỗi đối tượng là những biến trong
khai báo lớp của đối tượng hoặc lớp cha của nó. Khi nhận được một tham chiếu đến
một đối tượng thì JVM phải có khả năng định vị nhanh dữ liệu cho đối tượng.
Ngoài ra, phải có cách nào đó để truy cập được lớp dữ liệu lớp của đối tượng (lưu
trữ trong vùng phương thức) đưa cho việc tham chiếu tới đối tượng. Lý do này, bộ
nhớ được cấp phát cho đối tượng thông thường bao gôm một số kiểu con trỏ vào
trong vùng phương thức.
Một khả năng thiết kế heap là có thể chia heap thành 2 phần: một vùng điều
khiển và một vùng đối tượng. Một tham chiếu đối tượng là một con trỏ có sẵn trỏ
tới mục ở vùng điều khiển. Cái handle pool ( vùng quản lý chung) gồm 2 bộ phận:
một con trỏ liên kết đến dữ liệu cài đặt trong vùng object pool ( các đối tượng
chung) và một con trỏ đến dữ liệu của lớp đặt trong vùng methor area( vùng phương
thức). Ưu điểm của mô hình này là nó làm cho máy ảo java dễ dàng chống lại sự
phân mảnh của bộ nhớ heap. Khi máy ảo Java chuyển một đối tựong trong vùng đối
tựong chung, nó chỉ cần cập nhật một con trỏ với một địa chỉ mới của đối tựong:
con trỏ thích hợp trong vùng quản lý chung. Hạn chế của phương pháp này là mỗi
lần truy cập tới một thực thể dữ liệu của đối tượng yêu cầu hai con trỏ. Cách tiếp
cận mô tả đối tượng này được thể hiện bằng đồ thị cho trong hình 12-5. Loại heap
này giải thích sự tương tác bởi HeapOfFish applet, miêu tả trong Chương 9,
“Garbage Collection”
Hình 12-4: Splitting an object across a handle pool and object pool.
Một thiết kế khác thì một tham chiếu đến đối tượng là một con trỏ cơ sở
tham chiếu đến một gói dữ liệu chứa các dữ liệu của đối tượng và một con trỏ trỏ
đến dữ liệu lớp của đối tượng đấy. Hướng tiếp cận này chỉ yêu cầu chỉ một con trỏ
truy nhập tới dữ liệu thể hiện của một đối tượng, nhưng việc di chuyển đối tượng
phức tạp hơn. Khi máy ảo di chuyển một đối tượng để tránh sự phân mảnh của loại
heap này, nó phải cập nhật mọi sự tham chiếu tới đối tượng đó bất cứ nơi đâu trong
những vùng dữ liệu khi chạy. Cách tiếp cận này miêu tả đối tượng được thể hiện
bằng đồ thị trong hình 12-5.
Hình 12-5: Dữ tất cả các đối tượng dữ liệu trong một vùng trống.
Một điều chú ý nữa là việc sử dụng bảng phương thức trong việc tăng tốc việc
gọi các phương thức của đối tượng=> Giúp cho máy ảo Java đạt hiệu suất cao.
Nó không nằm trong những yêu cầu bắt buộc của đặc tả máy ảo Java.=>
không phải mọi cài đặt đều phải có cái này. Những thực thi mà có bộ nhớ thấp có
thể không đáp ứng được yêu cầu bộ nhớ của bảng phương thức.
Một cách để một thực thi có thể kết nối đến một bảng phương thức được cho
như hình vẽ.
Trong Java thì mảng là một đối tượng thực sự. Giống các đối tượng khác thì
nó cũng được lưu trữ trong vùng nhớ heap.
Các đối tượng có cùng chiều và kiểu các phần tử thì thuộc cùng một lớp.
Tên lớp của một mảng có cấu trúc là một dấu ngoặc vuông mở cộng với một
chữ cái biểu diễn lớp
Vd: mảng 3 phần tử int có tên lớp là “[I”. Mảng 2 chiều gồm các đối tượng có
tên lớp là “[[java.lang.Objects”. Mảng n chiều là mảng của các mảng n-1 chiều.
Dữ liệu lưu giữ cho trên bộ nhớ heap cho mỗi mảng là độ dài mảng, dữ liệu
mảng, và một vài kiểu của tham chiếu đến dữ liệu lớp của mảng. Khi nhận được
một tham chiếu đến mảng thì JVM có thể truy cập đến các phần tử của mảng qua
chỉ mục, và có thể gọi bất cứ hàm nào của lớp Object, là lớp cha trực tiếp của lớp
đối tượng mảng.
Thanh ghi đếm chương trình
Mỗi một luồng của một chương trình thì có thanh ghi PC của nó, thanh ghi PC
được khởi tạo lúc luồng được tạo. Nó có kích thước 1 từ, do đó nó có thể chứa cả
con trỏ cơ sở và giá trị trả về. Khi một luồng thực thi một phương thức thì PC sẽ
chứa chỉ thị hiện tại đang thực thi bởi luồng. Địa chỉ ở đây có thể là con trỏ cơ sở
hoặc độ dịch offset so với địa chỉ bắt đầu của mã bytecode của phương thức. Nếu
một luồng thực thi một con trỏ cơ sở thì giá trị của PC là không được định nghĩa
(undefined).
Frame có thể được cấp phát ở vùng nhớ liên tục của ngăn xếp hoặc ở vùng nhớ
động heap. Cấu trúc dữ liệu thực sự của ngăn xếp Java và stack frame phụ thuộc
vào những người thiết kế cài đặt.
12.2.7.1 Stack frame
Khung ngăn xếp có 3 phần: các biến cục bộ, ngăn xếp toán hạng và dữ liệu
khung. Kích thước của các biến cục bộ, ngăn xếp toán hạng được tính toán bằng số
lượng từ ( word), được xác định vào thời điểm biên dịch, được ghi lại trong các file
.class của mỗi phương thức. Còn kích thước của dữ liệu khung phụ thuộc vào chi
tiết cài đặt, được xác định tại thời điểm thực thi, khôgn thể thay đổi
Vùng biến cục bộ
Được tổ chức thành mảng các từ zero-based. Khi chỉ lệnh nào sử dung giá trị
biến nào đó thì sẽ cung cấp chỉ số cho các thành phần trong mảng để trỏ tới dữ liệu
đó.
Trước hết, các tham số của phương thức sẽ được lưu vào theo thứ tự khai báo.
Sau đó các biến cục bộ có thể được lưu vào tiếp sau, không cần theo thứ tự
Các kiểu dữ liệu int, float, reference và returnAddress chiếm một mục trong
mảng đó.
Còn kiểu long, double chiếm 2 mục trong mảng.
Giá trị kiểu char, byte, short được chuyển thành kiểu int trước khi lưu vào
vùng biến cục bộ.
Ví dụ:
public static int runClassMethod(int i, long l,
float f,
double d, Object o, byte b) {
return 0;
}
public int runInstanceMethod(char c, double d, short
s,
boolean b) {
return 0;
}
Hình 12-8: Method parameters on the local variables section of a Java stack.
Trong hình trên, ta thấy tham số đầu tiên trong vùng biến cục bộ của phương
thức runInstanceMethod() có kiểu tham chiếu reference mặc dù trong đoạn mã
nguồn không có tham số nào như vậy. Đây là tham số ẩn, được truyền vào đối với
mỗi thể hiện của phương thức. Phương thức thể hiện này sử dụng tham số ẩn đó để
truy cập tới các dữ liệu thể hiện của đối tượng dựa trên những gì chúng được gọi.
Vì phương thức static không có tham số nào như thế, nên ta không thể truy cập
tới dữ liệu thể hiện của lớp vì khôgn có thực thể nào gắn với lời gọi phương thức
đó.
Các kiểu byte, short, char và boolean trong mã nguồn trở thành kiểu int trong
vùng biến cục bộ và ngăn xếp toán hạng. Các kiểu dữ liệu hỗ trợ trực tiếp bởi máy
ảo Java có thể được lưu trữ trên heap như các thể hiện của biến hoặc thành phần của
mảng hoặc trong vùng nhớ phương thức như biến của lớp. Các kiểu dữ liệu được
chuyển thành int cũng sẽ được chuyển lại thành nguyên gốc trước khi lưu lại vào
trong vùng heap hoặc trong vùng phương thức.
Rất nhiều chỉ lệnh trong tập lệnh của máy ảo Java chỉ dẫn tới vùng hằng số.
Những chỉ lệnh này đẩy các giá trị hằng số kiểu int, long, float, double, hoặc string
từ vùng hằng số lên ngăn xếp toán hạng. Một vài chỉ lệnh này sử dụng các mục ở
vùng hằng số để chỉ dẫn tới các lớp hoặc mảng, tới ví dụ, trường dữ liệu để truy cập
hoặc phương thức được gọi. Các chỉ thị khác xác định liệu đối tượng riêng biệt là
thừa kế từ lớp riêng biệt hoặc giao diện hay không được chỉ ra bởi các mục trong
vùng hằng số.
Khi máy ảo Java gặp bất cứ câu lệnh nào chỉ tới vùng constant pool, nó sử
dụng con trỏ của khung ngăn xếp tới vùng đó. Khi tham chiếu tới các kiểu dữ liệu ở
vùng đó thì tức là khi đó khởi đầu kí tự, và máy ảo Java phải xử lý tham chiếu này
tại thời điểm đó.
Bên cạnh đó, dữ liệu khung cũng phải tham gia trong việc xử lý sự kết thúc
bình thường hoặc bất thường của một phương thức. Nếu phương thức kết thúc bình
thường, thì máy ảo phải trả lại khung ngăn xếp (có cả dữ liệu khung) của lời gọi
phương thức đó. Nó phải đặt thanh ghi pc trỏ tới câu lệnh trong phương thức được
gọi theo sau chỉ lệnh gọi sự hoàn thành của phươgn thức. Nếu phương thức trả về
giá trị, máy ảo phải đẩy kết quả lên ngăn xếp toán hạng của phương thức được gọi
đó.
Khung dữ liệu có thể gồm một vài tham chiếu tới bảng ngoại lệ của phương
thức, được máy ảo sử dụng để xử lý bất cứ ngoại lệ nào được ném ra trong quá trình
thực thi của phương thức đó. ( Chi tiết về ngoại lệ được nêu ở chương 17). Mỗi mục
trong bảng ngoại lệ có điểm đầu và điểm cuối của phạm vi mệnh đề catch, một chỉ
số trong vùng hằng số chỉ tới lớp ngoại lệ được bắt, và vị trí đầu của mã mệnh đề
catch.
Khi phương thức ném ra ngoại lệ, máy ảo Java sử dụng bảng ngoại lệ được chỉ
ra bởi dữ liệu khung để xác định cách điều khiển ngoại lệ đó. Nếu máy ảo tìm thấy
mệnh đề catch phù hợp thì nó sẽ chuyển quyền điều khiển cho điểm bắt đầu mệnh
đề catch. Nếu không, phương thức sẽ kết thúc bất thường.
Ngoài ra, khung ngăn xếp cũng có thể chứa các thông tinh khác, phụ thuộc vào
cài đặt: như dữ liệu hỗ trợ gỡ lỗi.
Chi tiết cài đặt của ngăn xếp Java
Xem ví dụ như sau:
class Example3c {
Chỉ lệnh gọi phương thức addTwoType() chỉ dẫn tới vùng hằng số. Máy ảo sẽ
tìm kiếm và giải quyết các vấn đề cần thiết trước khi sử dụng phương thức đó. Mặc
dù tham chiếu tới các phương thức, trường khác của lớp thì ở cùng một lớp, tham
chiếu trong vùng hằng số bao giờ cũng được khởi tạo là kí hiệu và được xử lý trước
khi thực hiện thực thi tiếp theo.
Việc xử lý này thực chất là tìm thông tin trong vùng hằng số chỉ tới thông tin
của phương thức trong vùng phương thức. Sau đó máy ảo Java sẽ sử dụng thông tin
đó xác định kích thước của phương thức này (addTwoType() ). (Có thể trên nền
SDK thì kích thuơc vùng biến cục bộ của phương thức này yêu cầu 3 từ nhớ, và 4 từ
nhớ của ngăn xếp toán hạng)
Khi phương thức addTwoType thực thi, nó sẽ lấy 2 giá trị vùng ngăn xếp toán
hạng của phương thức gọi (addAndPrint() ) đặt vào vùng biến cục bộ. Khi lấy giá trị
trả về thì kết quả được lưu trong stack toán hạng của phương thức addTwoType().
Dựa vào dữ liệu khung, phương thức hiện thời (addTwoType ) sẽ định vị phương
thức gọi nó ( addAndPrint) và giải phóng phương thức hiện thời, quay trở lại tiếp
tục thực thi phương thức gọi nó.
Một cách thực thi khác của đoạn mã nguồn giống ở trên là sử dụng cấp phát
liên tục trong stack.. Trong cách cài đặt này, toàn bộ ngăn xếp toán hạng của
phương thức addAndPrint() trở thành phần biến cục bộ của phương thức
addTwoType():
Hình 12-12: The stack for a thread that invokes Java and native methods.
Cũng giống như vùng nhớ thời gian chạy khác, vùng nhớ của ngăn xếp
phương thức cơ sở không cần có kích thước cố định. Một vài cài đặt có thể cho
phép người sử dụng và các nhà lập trình chỉ ra kích thước khởi đầu của vùng
phương thức cũng như kích thước tối thiểu và tối đa của nó.
− Chính là phần thực thi tiếp theo của opcode hiện tại
− Tìm kiếm mệnh đề catch phù hợp ( nếu chỉ thị là ném ngoại lệ)
Các luồng bytecode có thể phân chia thành các đoạn gợi nhớ.
Trọng tâm của tập chỉ lệnh của máy ảo Java là ngăn xếp toán hạng.
Các tập chỉ thị được coi như các biến cục bộ, hoặc như tập thanh ghi được
tham chiếu bởi chỉ số.
Việc thiết kế tập chỉ lệnh máy ảo Java:
Mục tiêu cần trong thiết kế là độc lập nền, khả chuyển mang tính hệ
thống, và an toàn.
Để đạt được đọc lập nền, việc cà i đặt máy ảo Java được thực hiện dễ dàng trên
phạm vi lớn các kiến trúc máy khác nhau: hướng ngăn xếp.
Kiến trúc hướng ngăn xếp của tập chỉ lệnh máy ảo Java làm việc tối ưu hóa dễ
dàng, có thể thực hiện tại thời gian chạy cùng với máy thực thi thực hiện việc biên
dịch JIT hoặc tối ưu thích nghi ( adaptive optimization ).
Để đạt được tính khả chuyển hệ thống: Để tăng tốc độ truyền file qua mạng
nên việc thu gọn file rất quan trọng. Do đó thiết kế sao cho tổng số mã toán tử
(opcode) chỉ cần biểu diễn trong 1 byte.
Để đạt được tính an toàn thì cần xác minh các bytecode. Việc xác minh có thể
được thực hiện trên từng chỉ lệnh hoặc trên dòng dữ liệu. Do đó hầu hết các opcode
nên xác định trước các kiểu dữ liệu mà chúng sẽ thực hiện thao tác trên đó.
12.2.8.2 Kĩ thuật thực thi
Có một vài kĩ thuật phổ biến có thể sử dụng là
− Thông dịch
Kĩ thuật tối ưu thích nghi có rất nhiều ưu điểm, và sẽ được mô tả chính ở đây.
Việc tối ưu thích nghi sẽ tận dụng được thông tin chỉ có trong thời gian thực thi.
Kĩ thuật này bắt đầu thông dịch toàn bộ mã, nhưng sẽ tập trung vào cách điều
chỉnh việc thực thi của mã. Máy ảo java có thể định hình phương thức thể hiện điểm
“hot-spot” của chương trình: khoảng 10-20 % mã được thực thi trong 80-90 % thời
gian. Sau khi xác định điểm “hot-spot”, nó sẽ gọi lại tiến trình nền biên dịch những
đoạn mã này thành cơ sở và tập trung tối ưu thành mã cơ sở (có thể thực thi được
ngay, nhanh chóng). Vì chỉ cần tập trung biên dịch và tối ưu “hot-spot” nên có thêm
thời gian tối ưu nữa. Sau đó một phương thức có thể di chuyển ra ngoài “hot-spot”,
máy ảo sẽ loại bỏ mã đó, và trở lại thông dịch chúng. Không giống như máy ảo biên
dịch JIT , kĩ thuật này không thực hiện việc tối ưu sớm. Mà nó chỉ bắt đầu từ
bytecode thông dịch được. Khi chương trình chạy, máy ảo “profile” chương trình để
tìm ra “hot spot”.
Giao diện phương thức cơ sở
Cài đạt máy ảo Java không yêu cầu hỗ trợ bất cứ giao diện phương thức cơ sở
đặc biệt nào. Một vài cài đặt có thể hỗ trợ hoặc không. Ví dụ: Giao diện cơ sở Java
của SUN, JNI được kết hợp để hỗ trợ tính khả chuyển. Điều này cho phép các nhà
phát triển có thể liên kết các mã nhị phân của phương thức cơ sở giống nhau tới bất
cứ cài đặt máy ảo nào hỗ trợ JNI, trên một nền máy chủ đặc biệt.
Để đạt được mục tiêu đó, người thiết kế có thể quyết định đưa ra giao diện
phương thức cơ sở ở mức độ thấp tương đối gắn chặt với cấu trúc của thực thi riêng
biệt của họ.
Mỗi phương thức cơ sở phải có thể tương tác ở mức độ nào đó với trạng thái
bên trong thực thể máy ảo Java. Ví dụ, giao diện có thể hỗ trợ một vài hoặc tất cả
các thao tác:
− Truyền vào và trả lại dữ liệu
− Truy cập tới thể hiện của biến hoặc gọi phương thức của đối tượng trên
vùng heap được thu gom bộ nhớ
− Truy cập biến của lớp hoặc gọi phương thức lớp
− Khóa đối tượng trên vùng heap để luồng hiện thời sử dụng độc quyền
− Tạo mới đối tượng trên vùng heap được thu gom bộ nhớ
− Bắt ngoại lệ ném bởi phương thức Java mà được gọi từ phương thức cơ
sở
− Bắt ngoại lệ không đồng bộ ném bởi máy ảo
− Xác định việc không cần thiết thu gom bộ nhớ với các đối tượng đặc
biệt.
Việc thiết kế giao diện phương thức cơ sở đòi hỏi một số dịch vụ phức tạp
− Phải đảm bảo bộ thu hồi bộ nhớ không được giải phóng bất cứ đối tượng
nào đang được dùng bởi phương thức cơ sở
− Nếu phải di chuyển đối tượng để giữ sự phân mảng heap ở mức nhỏ
nhất, thì phải đảm bảo một trong hai điều kiện:
1. Đối tượng có thể di chuyển sau khi tham chiếu được truyền vào một
phương thức cơ sở
2. Bất cứ đối tượng nào mà tham chiếu được truyền vào phương thức cơ
sở được giữ chặt cho tớikhi trả về giá trị hoặc xác định nó được hoàn
thành với một đối tượng.