2012-02-10 40 views
10

Tôi đã sử dụng Javassist để điều khiển động các lớp khi chúng được tải. Trong khi thêm mã vào một phương thức tương đối dễ dàng bằng cách sử dụng Javassist, tôi không thể tìm thấy cách để xóa mã.Xóa hướng dẫn khỏi mã Java bytecode

Tại thời điểm này, tôi đang mô phỏng việc xóa mã bằng cách sử dụng các hướng dẫn nop để thay thế các mã opcode được nhắm mục tiêu và bất kỳ thông số nào. Tuy nhiên, tôi coi đây là chủ yếu là một hack:

  • Mỗi opcode phải được xử lý riêng, vì độ dài byte của các thông số khác. Trong một số trường hợp, tôi cũng cần phải chọn giữa noppop, tùy thuộc vào việc opcode đã xóa có ảnh hưởng đến chồng hay không. Loại thao tác này bắt đầu trở nên tẻ nhạt - và mã mà nó đang dần trở nên phức tạp. Vì vậy, tự nhiên, tôi hy vọng cho một giải pháp hiện có.

  • Kết quả cuối cùng được điền với các hướng dẫn nop. Trong khi JVM nên tối ưu hóa chúng ra mà không có tác động hiệu suất, kết quả bytecode vẫn còn khá không phù hợp và lớn hơn mức cần thiết. Đây là một vấn đề về thẩm mỹ, nhưng nó vẫn là điều cần cân nhắc.

Thật không may, chỉ đơn thuần dịch các phần của mảng bytecode để đóng khoảng trống là không đủ - bất kỳ tham chiếu nào đến mã đã di chuyển (ví dụ: chỉ mục hướng dẫn chi nhánh) cũng phải được cập nhật.

Có thể xóa hướng dẫn bằng Javassist không? Ngoài ra, có một thư viện thao tác bytecode mà sẽ cho phép tôi làm điều đó một cách dễ dàng, mà không cần phải phân tích bản thân bytecode bản thân mình?

+2

Tôi chỉ tò mò thôi. Tại sao bạn muốn làm nó? Sẽ không dễ dàng hơn để dịch ngược các lớp, sửa đổi chúng và biên dịch lại chúng? – Luixv

+0

@Luixv: Tôi muốn quy trình thao tác diễn ra tự động trong thời gian chạy - sửa đổi mã nguồn thực tế theo cách thủ công không phải là một tùy chọn, bởi vì các phép biến đổi không cố định. – thkala

+0

Nếu bạn đặt lớp trong một 'jar', thì' nop' thừa sẽ được nén khá tốt và kích thước nén sẽ không lớn hơn nhiều. –

Trả lời

3

Apache BCEL cho phép bạn delete instructions:

Xóa các hướng dẫn cũng rất đơn giản; tất cả các lệnh điều khiển và các lệnh chứa trong một phạm vi nhất định được loại bỏ khỏi danh sách lệnh và được xử lý. Tuy nhiên, phương thức delete() có thể ném một TargetLostException khi có các trình hướng dẫn hướng dẫn vẫn tham chiếu đến một trong các lệnh đã xóa. Người dùng buộc phải xử lý các ngoại lệ như vậy trong một mệnh đề try-catch và chuyển hướng các tham chiếu này đến nơi khác.

Bạn cũng có thể tìm thấy ví dụ trong hướng dẫn.

+0

+1 Tôi chưa xem BCEL, nhưng nó có vẻ đầy hứa hẹn. Tôi sẽ thấy việc kết hợp trong mã hiện tại của tôi dễ dàng như thế nào ... – thkala

0

Từ hướng dẫn Javassist:

Javassist không cho phép để loại bỏ một phương pháp hoặc trường, nhưng nó cho phép thay đổi tên. Vì vậy, nếu một phương thức không cần thiết nữa, nó phải được đổi tên và thay đổi thành một phương thức riêng bằng cách gọi setName() và setModifiers() được khai báo trong CtMethod.

+0

Tôi không muốn xóa phương thức - Tôi muốn xóa hướng dẫn từ * trong * phương thức ... – thkala

+0

Rất tiếc, tôi đã thất bại! Tuy nhiên, để hoàn thành, hướng dẫn cũng nói rằng: 'Để loại bỏ một trường hoặc một phương thức, hãy gọi removeField() hoặc removeMethod() trong CtClass.' :S – user1205938

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