Trước hết, có một số khái niệm khác nhau về loại. Có các loại thời gian biên dịch, bao gồm generics. Tuy nhiên, Generics không tồn tại sau thời gian biên dịch.
Có xác minh loại tĩnh được phỏng đoán của một biến, có thể là int, float, long, double, returnaddress hoặc tham chiếu đối tượng. Các tham chiếu đối tượng được thêm vào với một giới hạn trên, để tất cả các tham chiếu là các kiểu con của ví dụ java/lang/String
. Các trường có thể có thêm một trong các loại ngắn: byte, short, char hoặc boolean. Chúng được xử lý giống hệt với int cho mục đích thực hiện nhưng có dung lượng lưu trữ khác nhau.
Cuối cùng, có kiểu thời gian chạy, giống như kiểu tĩnh được xác minh, nhưng trong trường hợp tham chiếu đối tượng, thể hiện loại thực tế của cá thể đang được tham chiếu. Lưu ý rằng do sự lười biếng xác minh, có một số trường hợp loại thời gian chạy có thể không thực sự là loại phụ của loại được xác minh. Ví dụ, một biến khai báo kiểu Comparable
thực sự có thể giữ bất kỳ đối tượng nào trong Hotspot vì VM không kiểm tra giao diện tại thời điểm xác minh.
Thông tin thời gian biên dịch không được lưu giữ ngoại trừ thông qua các thuộc tính tùy chọn để phản ánh và gỡ lỗi. Điều này là bởi vì không có lý do gì để giữ nó.
Biến cục bộ không có thông tin loại rõ ràng (ngoại trừ thuộc tính StackMapTable mới, nhưng đó là tính kỹ thuật). Thay vào đó, khi lớp được nạp, trình xác minh bytecode sẽ nhập một kiểu cho mỗi giá trị bằng cách chạy một phân tích dữ liệu tĩnh. Mục đích của việc này không phải là để bắt lỗi như kiểm tra kiểu thời gian biên dịch có thể, bởi vì nó được giả định rằng bytecode đã trải qua việc kiểm tra như vậy tại thời gian biên dịch.
Thay vào đó, mục đích xác minh là để đảm bảo rằng các hướng dẫn không gây nguy hiểm cho bản thân máy ảo. Ví dụ, nó cần phải chắc chắn rằng bạn không dùng một số nguyên và interperting nó như là một tham chiếu đối tượng, bởi vì điều đó có thể dẫn đến truy cập bộ nhớ tùy ý và hack máy ảo.
Vì vậy, trong khi giá trị bytecode không có thông tin loại rõ ràng, chúng có loại ngầm định là kết quả của suy luận kiểu tĩnh. Chi tiết về sự thay đổi này dựa trên các chi tiết thực hiện bên trong của từng máy ảo, mặc dù chúng là được cho là để tuân theo tiêu chuẩn JVM. Nhưng bạn sẽ chỉ phải lo lắng về điều đó trong bytecode viết tay.
Các trường có loại rõ ràng vì VM cần biết loại dữ liệu nào đang được lưu trữ trong đó. Các tham số của phương thức và các kiểu trả về được mã hóa trong cái được gọi là một bộ mô tả phương thức, cũng được sử dụng trong việc kiểm tra kiểu. Họ không thể suy ra tự động vì các giá trị này có thể đến từ hoặc đi bất cứ đâu, trong khi kiểm tra kiểu được thực hiện trên cơ sở mỗi lớp.
P.S. Tôi đã để lại một số chi tiết nhỏ khi nói về các loại xác minh. Các kiểu đối tượng bổ sung theo dõi xem chúng đã được khởi tạo hay chưa, và lệnh nào đã tạo chúng nếu chưa được khởi tạo. Các loại địa chỉ theo dõi mục tiêu của jsr đã tạo chúng.
Tôi nghi ngờ rằng các giá trị kiểu đã được kiểm tra tại 'thời gian biên dịch' dẫn đến mã không còn cần phải có thông tin giá trị kiểu, chỉ dữ liệu nhị phân. Các tham số của phương thức & các giá trị trả lại, tuy nhiên được gọi tại 'run-time' và yêu cầu thông tin cho kiểu kiểm tra –
cảm ơn, điều đó có ý nghĩa! – JB2
Vì đó là cách thức của nó. Trình xác minh JDK sử dụng phân tích dataflow để tìm ra loại "tiếp cận" với từng dữ liệu sử dụng. Các tham số và instance/static vars cần phải có kiểu khai báo để đưa vào dataflow. Loại kết quả tính toán, OTOH, có thể được xác định bởi các quy tắc. Bên cạnh đó, các vars cục bộ thường biến mất thành các giá trị stack khi được biên dịch. –