2012-02-16 12 views
9

मुझे प्रोग्राम किए गए किसी भी जार फ़ाइल में संकलित कक्षाओं, इंटरफेस और enums की संख्या गिनने की आवश्यकता है (इसलिए मुझे तीन अलग-अलग संख्याओं की आवश्यकता है)। कौन सी एपीआई मेरी मदद करेगी? (मैं तीसरे पक्ष के पुस्तकालयों का उपयोग नहीं कर सकता।)प्रोग्राम फ़ाइल के विश्लेषण के लिए

मैंने पहले से ही काफी मुश्किल योजना की कोशिश की है जो हमेशा सही नहीं लगता है। अर्थात्, मैंने प्रत्येक ZipEntry को बाइट [] में पढ़ा है और उसके बाद परिणाम को मेरे कस्टम क्लास लोडर को खिलाया है जो मानक CalssLoader को बढ़ाता है और बस इस बाइट [] को ClassLoader.defineClass (जिसे सुरक्षित है और सीधे एप्लिकेशन कोड से नहीं कहा जा सकता)। पूर्ण कोड on the Pastebin है।

+0

क्या आप 'ZipEntry.getName() 'को कॉल कर सकते हैं और देख सकते हैं कि यह 'class' फ़ाइल है या नहीं? या क्या आपको अलग-अलग कक्षाओं और इंटरफेस (और enums?) गिनने की आवश्यकता है? – DNA

+0

मुझे उन्हें अलग से गिनने की आवश्यकता है (इसके अलावा यह ज्ञात है कि सभी .class-files में सही बाइट कोड नहीं है)। –

+0

गलत बाइट कोड वाले .class-files हम गिनना नहीं चाहते हैं। –

उत्तर

10

एक जार फ़ाइल एक विशिष्ट पैटर्न के साथ एक ज़िप फ़ाइल है। आप एक ज़िपफाइल और ज़िपइन्ट्री या उनके बच्चों के वर्ग जारफाइल और जारेंन्ट्री का उपयोग कर सकते हैं।

यह कोड (कस्टम क्लासलोडर का एक तरीका) आपको आवश्यक प्रत्येक प्रकार की "कक्षा" के सरणी के साथ एक मानचित्र वापस कर देगा।

public Map<String, List<Class<?>>> loadAndScanJar(File jarFile) 
     throws ClassNotFoundException, ZipException, IOException { 

    // Load the jar file into the JVM 
    // You can remove this if the jar file already loaded. 
    super.addURL(jarFile.toURI().toURL()); 

    Map<String, List<Class<?>>> classes = new HashMap<String, List<Class<?>>>(); 

    List<Class<?>> interfaces = new ArrayList<Class<?>>(); 
    List<Class<?>> clazzes = new ArrayList<Class<?>>(); 
    List<Class<?>> enums = new ArrayList<Class<?>>(); 
    List<Class<?>> annotations = new ArrayList<Class<?>>(); 

    classes.put("interfaces", interfaces); 
    classes.put("classes", clazzes); 
    classes.put("annotations", annotations); 
    classes.put("enums", enums); 

    // Count the classes loaded 
    int count = 0; 

    // Your jar file 
    JarFile jar = new JarFile(jarFile); 
    // Getting the files into the jar 
    Enumeration<? extends JarEntry> enumeration = jar.entries(); 

    // Iterates into the files in the jar file 
    while (enumeration.hasMoreElements()) { 
     ZipEntry zipEntry = enumeration.nextElement(); 

     // Is this a class? 
     if (zipEntry.getName().endsWith(".class")) { 

      // Relative path of file into the jar. 
      String className = zipEntry.getName(); 

      // Complete class name 
      className = className.replace(".class", "").replace("/", "."); 
      // Load class definition from JVM 
      Class<?> clazz = this.loadClass(className); 

      try { 
       // Verify the type of the "class" 
       if (clazz.isInterface()) { 
        interfaces.add(clazz); 
       } else if (clazz.isAnnotation()) { 
        annotations.add(clazz); 
       } else if (clazz.isEnum()) { 
        enums.add(clazz); 
       } else { 
        clazzes.add(clazz); 
       } 

       count++; 
      } catch (ClassCastException e) { 

      } 
     } 
    } 

    System.out.println("Total: " + count); 

    return classes; 
} 
+0

बहुत बहुत धन्यवाद, यह लगभग पूरी तरह से काम करता है। कुछ मामूली विवरण: 'super.addURL' का उपयोग करने में सक्षम होने के लिए आपको 'URLClassLoader' को' क्लासलोडर' 'नहीं बढ़ाया जाना चाहिए। और फिर आपको कन्स्ट्रक्टर को परिभाषित करना होगा जो यूआरएल की सरणी के साथ 'सुपर' कहता है। काश मैं इसे शून्य से खिला सकता हूं, लेकिन अपवाद मिला। तो मैंने एक यूआरएल के साथ एक सरणी का निर्माण किया जो मेरे जार से मेल खाता है। –

+1

आप एक खाली सरणी पास कर सकते हैं ... यह ठीक काम करता है ... सुपर क्लास के बारे में गलतफहमी के बारे में खेद है, यह एक UrlClassloader है ... – Eldius

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