2011-12-12 8 views
6

Tôi đang cố gắng thực hiện một số xử lý lỗi trong bytecode java. đầu tiên tôi cố gắng thực hiện một số chương trình con bắt giống như, nơi tôi sẽ kiểm tra các điều kiện lỗi, và nhảy đến chương trình con thích hợp, một chút như:Xử lý các ngoại lệ Thử/Bắt trong mã Java bytecode? ("stack height inconsistent")

iconst_1 
    iconst_0 
    dup 
    ifeq calldiverr 
    goto enddivtest 
calldiverr: 
    jsr divError 
enddivtest: 
    idiv 

...More instructions... 

divError: 
    getstatic java/lang/System/out Ljava/io/PrintStream; 
    ldc "Oh dear you divided by 0!" 
    invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V 

Vấn đề với bên trên là khi tôi có nhiều hướng dẫn nhảy đến chương trình con này, tôi nhận được một thông báo lỗi khi chạy bytecode, nói rằng chiều cao ngăn xếp không phù hợp.

Có thể sử dụng ngoại lệ là cách tốt nhất để giải quyết vấn đề này?

Từ một số googling tôi đã phát hiện ra rằng bạn có thể tạo thể hiện của lớp Exception và khởi chúng với một cái gì đó như:

new java/lang/Exception 
dup 
ldc "exception message!" 
invokespecial java/lang/Exception/<init>(Ljava/lang/String;)V 

Tôi cũng đã phát hiện ra rằng bạn có thể ném chúng với athrow và điều này có vẻ ok.

Điều khiến tôi khó hiểu là chính xác cách ngoại lệ bị bắt. Dường như có một "bảng ngoại lệ" ma thuật, gắn kết việc ném và bắt các ngoại lệ với nhau, nhưng tôi không biết cách xác định một trong số này khi viết bytecode từ đầu (và lắp ráp bằng cách sử dụng Jasmin). Ai đó có thể cho tôi biết bí mật của việc tạo ra một bảng ngoại lệ? Và có thể cho tôi một ví dụ về xử lý ngoại lệ sẽ tập hợp với jasmin?

Trả lời

2

Cuối cùng tôi đã nghĩ ra ab giải pháp etter hơn jsr - xác định phương thức sử dụng .method trong Jasmin. Tôi vừa sử dụng invokestatic để gọi trình xử lý lỗi của mình khi tôi đã phát hiện lỗi.

Đối với những người đang tìm kiếm xử lý ngoại lệ thực tế - tôi nghĩ rằng việc xác định bảng ngoại lệ trong Jasmin có thể được thực hiện bằng cách sử dụng .catch, nhưng tôi chưa xem xét nó.

Edit:

tôi đã phải nhìn vào .catch cuối cùng, và thấy nó thực sự dễ sử dụng. Nó được ghi nhận là here.

0

Trước hết giá trị của nó chỉ ra rằng tệp lớp học từ phiên bản 51.0 không được chứa hướng dẫn jsr. Lặp lại mã hoặc sử dụng một phương thức.

Tại mỗi điểm trong bytecode, loại tĩnh của mọi phần tử trong khung phải được biết. Mỗi khung không phải là một ngăn xếp cuộc gọi.

Nói chung bạn không muốn chơi xung quanh với các ngăn xếp lớn lớn. Lưu trữ thời gian trong các biến cục bộ để giữ cho mọi thứ đơn giản.

Nếu ngoại lệ được ném thì rõ ràng khung có thể có nội dung từ bất kỳ nơi nào ngoại lệ có thể đã ném. Vì vậy, các nội dung được loại bỏ và thay thế bằng ngoại lệ. Bạn sẽ không thể quay lại và tiếp tục sử dụng nội dung khung.

0

Quy tắc xác minh jsr khá phức tạp và vì Tom đã chỉ ra opcode không được dùng nữa. Vì vậy, tốt nhất nên tránh.

bộ nhớ của tôi trên jsr là một chút mờ, nhưng ...

(Cập nhật) Có một quy tắc trong xác minh bytecode Java mà bất cứ nơi nào hai dòng kiểm soát tham gia cùng độ sâu ngăn xếp phải giống hệt nhau dọc theo hai nhánh. jsr chương trình con được miễn quy tắc này cho một điểm - nhiều điểm ngoại lệ với độ sâu ngăn xếp khác nhau có thể "tiếp cận" cùng một thói quen jsr, nhưng thay đổi ròng trong chiều sâu ngăn xếp từ jsr mục nhập thường lệ sau ret phải bằng 0 (hoặc thực sự là trừ 1 , vì nguyên nhân ngoại lệ luôn được đẩy vào mục nhập thường trình).

Hơn nữa, trong khi quy trình jsr có thể "thoát" và chuyển trở lại luồng điều khiển thông thường, nếu không, jsr sẽ không được miễn quy tắc độ sâu ngăn xếp cho điểm kết nối. Điều này hạn chế nghiêm trọng các tình huống mà bạn có thể làm điều này, vì một thói quen jsr có khả năng có thể được nhập với độ sâu ngăn xếp khác nhau.

(Và tôi đã không có nghi ngờ vẫn còn có một số sai đó, nhưng đó là tốt nhất tôi có thể làm.)

(Tôi hoàn toàn không hiểu làm thế nào bạn đang lập kế hoạch để "lấy xung quanh" jsr của bạn vấn đề với trường hợp ngoại lệ.)

(Ngoài ra, Sun làm bytecode viết phức tạp hơn nhiều với 4 hoặc 5 (không thể nhớ được), làm cho nó khá nhiều không thể mã bytecode tay. Họ đã làm điều này bởi vì họ không biết cách xác minh đủ nhanh để đánh bại trình xác minh của IBM nếu không, nhưng đó là một vấn đề khác.)

+0

Thực ra, hoàn toàn hợp pháp để có một 'jsr' không bao giờ' đọc lại. Các hạn chế về các chương trình con là 1) mỗi chương trình con có thể chứa chỉ một lần thử lại (vì vậy bạn không thể truy xuất cả hai nhánh của một nếu không tham gia chúng). 2) các cuộc gọi chương trình con phải tạo thành một cây. Ngoài ra, không có giới hạn bên cạnh những người áp đặt kiểm tra loại. – Antimony

+0

Phần thực sự phức tạp là định nghĩa chính xác về những gì được coi là nội dung của chương trình con, vì điều này phụ thuộc vào các chi tiết của thuật toán kiểm tra kiểu. May mắn thay, Hotspot là nguồn mở và bạn có thể tự xác định điều này như tôi có nếu bạn quan tâm. Đây là tệp có liên quan http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/tip/src/share/native/common/check_code.c. Rõ ràng, điều này phụ thuộc vào việc triển khai thực hiện, vì vậy nếu bạn quan tâm đến vms không phải là Hotspot, bạn nên đảm bảo rằng các trình con của bạn được cấu trúc tốt để tránh những sự mơ hồ như vậy. – Antimony

+0

@Antimony - Giống như tôi đã nói, bộ nhớ của tôi về các quy tắc cho jsr là mờ - chưa được nhét với người xác minh trong 5-6 năm nay. IIRC, mặc dù, các quy tắc cho những gì bên trong một chương trình con là khá thẳng về phía trước - để ở trong chương trình con, một điểm phải có thể truy cập được từ điểm vào và phải truy cập lại từ điểm được đề cập. Không nên có bất kỳ sự mơ hồ nào về điều đó. –