2013-04-14 44 views
10

Theo bài báo này http://slurp.doc.ic.ac.uk/pubs/observing/linking.html#assignment:Java bytecode: các loại biến cục bộ?

Do sự khác biệt về thông tin giữa các mã Java và bytecode (bytecode không chứa các loại biến địa phương), người xác minh không cần phải kiểm tra phân nhóm cho các bài tập để biến cục bộ hoặc cho tham số.

Câu hỏi của tôi: Tại sao bytecode không chứa thông tin kiểu cho biến cục bộ, trong khi nó thực sự chứa thông tin kiểu cho tham số và giá trị trả về?

+2

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 –

+0

cảm ơn, điều đó có ý nghĩa! – JB2

+1

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

Trả lời

5

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.

+0

Có thể đáng lưu ý rằng kiểu 'returnAddress' chỉ được sử dụng trong buổi hòa nhạc với các mã lệnh' jsr' và 'jsr_w', bị cấm trong Java 6. Các giá trị được điều khiển bởi bytecode hiện đại sẽ không bao giờ có' returnAddress'. –

+0

@Tom Chúng không thể được sử dụng trong một tệp lớp với phiên bản chính trên 49. Nhưng bạn vẫn có thể chạy các tệp lớp với số phiên bản thấp hơn trên các máy ảo hiện đại. Bạn có thể thiết lập phiên bản thấp như '45.0' nếu bạn muốn, và làm như vậy sẽ cho phép một số hành vi không có giấy tờ thú vị trong Hotspot. Nếu bạn chỉ xem xét bytecode được biên dịch bởi Java, có một số thứ mà javac tạo ra bytecode sẽ không bao giờ làm. Nhưng nó vẫn còn quan tâm đến tin tặc bytecode. – Antimony

+0

Đúng! Đó là một chút xấu hổ mà chúng tôi phải giữ cho tàu tuần dương này xung quanh, bởi vì nó giải thích cách bytecode hoạt động phức tạp hơn nhiều. –

2

Java bytecode giữ lại gõ thông tin về fields, methodreturnsparameters nhưng không, như bạn hỏi, chứa loại thông tin cho local variables.

Các loại thông tin trong tập tin lớp Java làm cho nhiệm vụ của decompilation của bytecode dễ dàng hơn decompilation của machine code. Giải mã mã byte Java, do đó, yêu cầu phân tích hầu hết các loại biến cục bộ, làm phẳng các hướng dẫn dựa trên ngăn xếp và cấu trúc của loopsconditionals. Nhiệm vụ giải mã bytecode, tuy nhiên, nhiều hơn khó hơn việc biên dịch. Bạn sẽ thấy các trình giải mã thông thường không thể thực hiện đầy đủ chức năng dự định của chúng

3

Đó là một giấy khá cũ. Các tệp lớp hiện tại do bao gồm các loại cho biến cục bộ và ngăn xếp. Các kiểu không được lưu trữ trong bytecode của phương thức, nhưng được lưu trữ trong một StackMapTable attribute được gắn vào phương thức.

Đó là (và luôn luôn) có thể xây dựng lại các loại của tất cả các biến cục bộ và các phần tử ngăn xếp bằng phân tích dữ liệu mà không có StackMapTable, nhưng nó là tốn kém tính toán. Mã số với StackMapTable có thể được xác minh nhanh hơn nhiều. Mặc dù tôi phải thú nhận rằng tôi không thấy làm thế nào xác minh các StackMapTable s có thể được nhanh hơn làm phân tích, nhưng sau đó tôi biết hầu như không có gì về việc này.

+0

Tôi ngưỡng mộ chuyên môn của bạn. Đối với tôi, bytecode giống như ma thuật ... và không ít phức tạp hơn. – scottb

+0

Tôi không thực sự có chuyên môn - tôi đã đọc các thông số kỹ thuật, nhưng đó là về nó. –

+0

StackMapTables chỉ cung cấp một loại cho các giá trị ở đầu mỗi khối cơ bản, do đó phân tích dataflow được yêu cầu để tạo lại các kiểu của tất cả các giá trị. Đặc biệt, mã tuyến tính có thể thậm chí không có thuộc tính 'StackMapTable'. Nó chỉ nhanh hơn bởi vì các dataflow không còn phải làm nhiều đi trong trường hợp của các vòng hoặc các chi nhánh. – Antimony

Các vấn đề liên quan