2012-04-20 26 views
7

Tôi đã viết một trình phân tích cú pháp bytecode Java bằng cách sử dụng Haskell và nó hoạt động tốt. Tuy nhiên, bước tiếp theo đã khiến tôi hoàn toàn bối rối.Tiêm một hàm vào tệp .class của Java bằng cách sử dụng Haskell

chương trình

My Haskell cần phải sửa đổi các tập tin .class do đó, khi thực hiện, chương trình in Java:

"Bước vào [phương pháp tên ở đây]" trước khi thực hiện một phương pháp, và

" Thoát [tên phương thức tại đây] "sau khi thực hiện một phương pháp.

Tất cả những gì tôi biết là chúng tôi sẽ cần phải nối thêm bảng và bảng phương thức không đổi với các cuộc gọi đến System.out.println, nhưng tôi cảm thấy tôi vẫn còn thiếu điều gì đó.

  • Cách tốt nhất để tiếp cận vấn đề này là gì?
  • Làm cách nào bạn biết cách gọi System.out.println bằng bytecode?
  • Làm cách nào để lưu trữ chuỗi có tên của phương pháp, sau này được gọi là đối số của System.out.println?
+2

[VMSpec] (http://docs.oracle.com/javase/specs/jvms/se5.0/html/ClassFile.doc.html#80959) là bạn của bạn. :) – biziclop

+1

tiêm chức năng mới vào bytecode ??? Tôi thực sự vui vì bạn đang gặp vấn đề với điều này nghe có vẻ đáng sợ – ControlAltDel

+1

Tôi không tin rằng bạn cần phải đi ra ngoài của Java cho một giải pháp này - Tôi nghi ngờ rằng một số loại kỹ thuật proxy sẽ làm việc. (Điều đó nói rằng, bạn có sự tôn trọng của tôi đối với cố gắng để làm điều đó theo cách này.;)) –

Trả lời

2

Vâng, đây là thư viện kỹ thuật mã byte khác nhau cung cấp cho bạn. ASM, BCEL, v.v. Các chi tiết cụ thể về bài tập ở nhà của bạn là một khía cạnh và AspectJ thực hiện chính xác điều đó.

Có vẻ như bài tập về nhà là viết một bài tập kỹ thuật mã byte Haskell, vì vậy bạn sẽ cần phải tự sửa đổi tệp lớp. Đề xuất ở trên bởi @biziclop là chính xác. Thực hiện trước và sau trên một tệp lớp, lưu ý vùng đồng bằng và tự làm như vậy từ Haskell.

[ps: tất nhiên, "cắt ngắn" ở trên: P là nếu bạn không thích đọc thông số JVM (như được ghi chú trong q của bạn) và tìm cách thực hiện như thể bạn nếu viết một trình biên dịch Java. Về cơ bản, bạn gọi một phương thức bằng cách sử dụng một trong các mã byte khác nhau để gọi - ở đây một cuộc gọi phương thức giao diện - trước khi bạn cần có bộ thu, ví dụ: trường tĩnh ra khỏi lớp Hệ thống và tên phương thức trên ngăn xếp. Thông tin chi tiết trong thông số kỹ thuật.]

2

Có lẽ cách tiếp cận dễ nhất là viết một lớp Java có một phương thức với mã System.out.println() trong đó, biên dịch với javac và quan sát kết quả.

Khi bạn đã quen thuộc với nó, hãy tiến hành từng bước.

  1. Thêm số System.out.println() gọi một nơi nào đó trong tệp java mà bạn muốn công cụ. Điều này sẽ chăm sóc hồ bơi không đổi. Viết mã Haskell để tìm các hằng số có liên quan và tiêm bytecode.
  2. Xóa cuộc gọi "nạng" khỏi tệp java và triển khai thao tác nhóm liên tục trong Haskell.
2

Chỉ cần lấy danh sách bytecode Java của bạn và mở một lớp được biên dịch đơn giản với lời gọi hàm tới System.out.println() và xem nhanh. Làm điều này cho bất cứ phương pháp nào bạn cần. Cách tốt nhất để tìm ra điều này là thực hiện một số điều tra với một số tệp mã đơn giản và kỹ sư đảo ngược khi bạn thực hiện. Bạn sẽ phải dịch thư bạn muốn thành unicode và chuyển nó vào hàm của bạn. Đừng quên về phần đó. Có nhiều chương trình khác nhau sẽ giúp bạn tìm kiếm để chinh phục bytecode.

0

Tôi nghĩ cách tốt nhất để tiếp cận vấn đề này là sử dụng thư viện Javassist (Java Programming Assistant). Javassist.bytecode lớp có một số chức năng có thể hữu ích.

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