2012-03-01 20 views
8

मैं कुछ जावा बाइटकोड संशोधन करने के लिए एएसएम लाइब्रेरी का उपयोग कर रहा हूं - विशेष रूप से एक नया इंटरफेस और संबंधित तरीकों को लागू करने के लिए अपने वर्गों को संशोधित करने के लिए। मेरा वर्तमान दृष्टिकोण कोर एएसएम एपीआई का उपयोग जावावांट के माध्यम से कर रहा है। मैं इस गतिशील दृष्टिकोण को स्थिर रूप से संशोधित .class फ़ाइलों के विरोध में रखना चाहता हूं।मैं एएसएम कोड के भीतर से Instrumentation.retransformClasses() को सही तरीके से कैसे उपयोग करूं?

उच्च स्तर पर, मेरी समस्या यह है कि यदि मैं बी से विस्तारित कक्षा ए को संशोधित करना चुनता हूं, तो मुझे बी को संशोधित करने की भी आवश्यकता है (मेरी समझ को देखते हुए कि जेवीएम में कक्षाएं कैसे लोड की जाती हैं, मुझे विश्वास है कि कक्षा बी को कक्षा ए से पहले एक ट्रांसफार्मर को हमेशा दिया जाएगा (अगर मैं गलत हूं तो कृपया मुझे सही करें)। धारणा को देखते हुए, मुझे लगता है कि मुझे वापस जाने की आवश्यकता है और बी को पुन: ट्रांसफर करने की आवश्यकता है। मेरा दृष्टिकोण इस पर कब्जा कर लिया गया है कोड के बिट:

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 जो निर्माता में में पारित हो जाता है Instrumentation करने के लिए एक संभाल है)

जिस भाग में मुझे मुश्किल समय है, वह **2** के साथ टिप्पणियों में चिह्नित ब्लॉक है। आइए फिर से कहें कि ए बी को बढ़ाता है और मैं ए को बदलने में 'दिलचस्पी' हूं। मुझे उम्मीद है कि मैं सुपरक्लास (बी) का नाम **1** पर मुद्रित कर रहा हूं (लेकिन यह नहीं बदला जा रहा है क्योंकि मैं नहीं बदल रहा लगता है कि यह पहले पास पर दिलचस्प है) और फिर, एक बार जब मैं **2** पर जाता हूं और पता चलता हूं कि ए का सुपरक्लास बी है, तो मुझे बी को पुन: ट्रांसफर करने की कोशिश करनी चाहिए। इस बिंदु पर मैं इस विधि को फिर से कॉल करने की उम्मीद कर रहा हूं (inst.retransformClasses() के माध्यम से) और कि मैं बी को **1** पर मुद्रित कर रहा हूं। हालांकि, मैं नहीं करता। (मैंने प्रिंट स्टेटमेंट्स जोड़े हैं और मुझे यकीन है कि मैं रेट्रांसफॉर्म कॉल तक पहुंच रहा हूं। मैंने यह भी देखा है कि Instrumentation.isRetransformClassesSupported() और Instrumentation.isModifiableClass(c) दोनों सत्य वापस आते हैं)।

मेरा मानना ​​है कि मैंने एजेंट को सही तरीके से स्थापित किया है; मैनिफेस्ट में Can-Retransform-Classes और Can-Redefine-Classes दोनों को सत्य में सेट करना। मैं गलत यहाँ क्या कर रहा

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

के रूप में किसी भी अंतर्दृष्टि: इसके अलावा, जब मैं एजेंट की premain विधि में इंस्ट्रूमेंटेशन के लिए ट्रांसफार्मर जोड़ने मैं यह कर? धन्यवाद।

+1

क्या आपने अपनी समस्या का समाधान किया है? @ जेन्स क्या आप [यहां] जा सकते हैं (http://stackoverflow.com/questions/18657095/got-unsupportedoperationx-hen-try-to-retransformclasses) मुझे कुछ सलाह देने के लिए? –

उत्तर

1

आप अपनी बाइटकोड वाद्ययंत्र रणनीति बदल सकते हैं, इसलिए जब कक्षा बी लोड हो जाता है, तो आप अपने सभी उप-वर्गों को पा सकते हैं और उस बिंदु पर निर्णय लेते हैं यदि आपको कक्षा बी को संशोधित करने की आवश्यकता है। इसे कक्षा में मेटाडेटा रिपोजिटरी या कैश को बनाए रखने के द्वारा अनुकूलित किया जा सकता है (यानी कक्षा पदानुक्रम के बारे में जानकारी), इसलिए आपको हर बार मेटाडेटा लोड नहीं करना पड़ेगा।

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^