2012-03-01 44 views
8

Tôi đang sử dụng thư viện asm để thực hiện một số sửa đổi bytecode Java - đặc biệt để sửa đổi các lớp của tôi để triển khai giao diện mới và các phương thức liên quan. Cách tiếp cận hiện tại của tôi là sử dụng API asm lõi thông qua một javaagent. Tôi muốn giữ cách tiếp cận năng động này trái ngược với các tệp .class tĩnh sửa đổi. Ở mức độ cao hơn, vấn đề của tôi là nếu tôi chọn sửa đổi lớp A, mở rộng từ B, tôi cũng cần phải sửa đổi B. (Với sự hiểu biết của tôi về cách các lớp được nạp trong JVM, tôi tin rằng lớp đó B sẽ luôn luôn được giao cho một biến áp trước khi lớp A. (Xin vui lòng sửa tôi nếu tôi sai) Giả sử rằng, tôi nghĩ rằng tôi sau đó cần phải quay trở lại và retransform B. Cách tiếp cận của tôi được chụp trong này chút mã:Làm thế nào để sử dụng Instrumentation.retransformClasses() một cách chính xác từ bên trong mã asm?

public byte[] transform(ClassLoader l, String name, Class<?> clazz, ProtectionDomain d, byte[] b) { 
     throws IllegalClassFormatException { 
    // **1** 
    System.out.println("--->>> " + name); 

    if (interestingClass(name)) { 
     try { 
      ClassReader cr = new ClassReader(b); 
      ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); 
      PyClassVisitorAdapter pv = new PyClassVisitorAdapter(cw, name); 
      cr.accept(pv, 0); 

      // **2** Retrieve the superclass and try to transform that 
      if (! "Ljava/lang/Object;".equals(pv.getSuperName())) { 
       String cName = classJvmToCanonical(pv.getSuperName()); 
       Class[] classes = inst.getAllLoadedClasses(); 
       for (Class c : classes) { 
        if (c.getName().equals(cName)) { 
         inst.retransformClasses(c); 
         break; 
        } 
       } 
      } 

      // Dump the transformed class 
      ClassReader cr2 = new ClassReader(cw.toByteArray()); 
      ClassWriter cw2 = new ClassWriter(cr2, 0); 
      TraceClassVisitor tcv = new TraceClassVisitor(cw2, new PrintWriter(System.out)); 
      cr2.accept(tcv, 0); 

      return cw2.toByteArray(); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
      return null; 
     } 
    } else { 
     return b; 
    } 
} 

(inst là một xử lý cho Instrumentation mà được thông qua ở trong constructor)

012.

Phần tôi đang gặp khó khăn là khối được đánh dấu trong các ý kiến ​​với **2**. Hãy nói lại rằng A mở rộng B và tôi 'quan tâm' trong việc chuyển đổi A. Điều tôi mong đợi là tôi sẽ thấy tên của siêu lớp (B) được in tại **1** (nhưng không bị biến đổi vì tôi không nghĩ rằng nó thú vị trên pass đầu tiên) và sau đó, khi tôi nhận được **2** và phát hiện ra rằng superclass của A là B, tôi nên cố gắng truyền lại B. Tại thời điểm này tôi hy vọng phương thức này sẽ được gọi lại (thông qua inst.retransformClasses()) và tôi sẽ thấy B được in tại **1**. Tuy nhiên, tôi không. (Tôi đã thêm báo cáo in và chắc chắn rằng tôi đang đạt đến cuộc gọi lại. Tôi cũng đã kiểm tra rằng Instrumentation.isRetransformClassesSupported()Instrumentation.isModifiableClass(c) cả hai đều trả về true).

Tôi tin rằng tôi đã thiết lập tác nhân chính xác; đặt cả hai lớp có thể chuyển giao lại và có thể xác định lại thành đúng trong tệp kê khai. Ngoài ra, khi tôi thêm các biến áp đến Instrumentation trong phương pháp của đại lý premain Tôi làm điều này:

public static void premain(String agentArgs, Instrumentation inst) { 
    inst.addTransformer(new PyClassFileTransformer(inst), true); 
} 

Bất kỳ hiểu biết sâu sắc như những gì tôi đang làm sai ở đây? Cảm ơn.

+1

Bạn có giải quyết vấn đề về ur không? @ Jens Bạn có thể đi [ở đây] (http://stackoverflow.com/questions/18657095/got-unsupportedoperationexception-when-try-to-retransformclasses) để cho tôi một số lời khuyên? –

Trả lời

1

Bạn có thể thay đổi chiến lược công cụ bytecode, vì vậy khi lớp B được tải, bạn sẽ tìm thấy tất cả các lớp con của nó và quyết định tại điểm đó nếu bạn cần sửa đổi lớp B ngay bây giờ. Điều này có thể được tối ưu hóa bằng cách duy trì kho lưu trữ siêu dữ liệu lớp hoặc bộ nhớ cache trong bộ nhớ (tức là thông tin về phân cấp lớp), do đó bạn sẽ không phải tải siêu dữ liệu mỗi lần.

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