2012-06-13 4 views
49

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

मुझे URLClassloader के आधार पर बहुत से समाधान मिल सकते हैं जो मुझे निर्देशिका/संग्रह से विशिष्ट वर्गों को लोड करने की अनुमति देते हैं, लेकिन कोई भी जो कक्षा वर्ग या पैकेज संरचना के बारे में कोई जानकारी के बिना कक्षाओं को लोड करने की अनुमति देगा।

संपादित करें: मुझे लगता है कि मैंने इसे खराब तरीके से phrased किया। मेरी समस्या यह नहीं है कि मुझे सभी कक्षा फाइलें नहीं मिल सकती हैं, मैं इसे रिकर्सन आदि के साथ कर सकता हूं और उन्हें सही तरीके से ढूंढ सकता हूं। मेरी समस्या प्रत्येक वर्ग फ़ाइल के लिए क्लास ऑब्जेक्ट प्राप्त कर रही है।

+1

आप अपने पूर्ण योग्य नाम को अनदेखा कर एक वर्ग कैसे लोड कर सकते हैं? मुझे नहीं लगता कि यह संभव है। –

+4

नीचे दिए गए उत्तरों आपको क्लास फाइलों का पता लगाने देंगे, लेकिन, आपके प्रोजेक्ट के आकार के आधार पर, यह [asm] (http://asm.ow2.org/) या [javassist] (http: // www.csg.ci.iu-tokyo.ac.jp/~chiba/javassist/)। ये आपको कक्षाओं को स्मृति में लोड किए बिना विश्लेषण करने देगा। –

उत्तर

87

निम्नलिखित कोड एक जेएआर फ़ाइल से सभी कक्षाओं को लोड करता है। कक्षाओं के बारे में कुछ भी जानने की जरूरत नहीं है। कक्षाओं के नाम जारेंट्री से निकाले जाते हैं।

JarFile jarFile = new JarFile(pathToJar); 
Enumeration<JarEntry> e = jarFile.entries(); 

URL[] urls = { new URL("jar:file:" + pathToJar+"!/") }; 
URLClassLoader cl = URLClassLoader.newInstance(urls); 

while (e.hasMoreElements()) { 
    JarEntry je = e.nextElement(); 
    if(je.isDirectory() || !je.getName().endsWith(".class")){ 
     continue; 
    } 
    // -6 because of .class 
    String className = je.getName().substring(0,je.getName().length()-6); 
    className = className.replace('/', '.'); 
    Class c = cl.loadClass(className); 

} 

संपादित करें:

ऊपर टिप्पणी में सुझाव के रूप में, javassist भी एक संभावना हो जाएगा। कहीं जबकि पाश से पहले एक ClassPool प्रारंभ उपरोक्त कोड के रूप में, और बदले वर्ग लोडर के साथ वर्ग को लोड करने की, तो आप एक CtClass वस्तु बना सकते हैं:

ClassPool cp = ClassPool.getDefault(); 
... 
CtClass ctClass = cp.get(className); 

ctClass से, आप सभी विधियां, फ़ील्ड प्राप्त कर सकते हैं https://jboss-javassist.github.io/javassist/html/index.html

+1

एक पुरानी पोस्ट लाने के लिए खेद है (इस उत्तर के लिए धन्यवाद btw, यह मेरे लिए काम करता है)। हालांकि, 'नया यूआरएल ("जार: फाइल:" + पथ टोजर + "! /")' 'क्लास नॉटफाउंड अपवाद 'का कारण बनता है। मेरे लिए क्या काम था: 'यूआरएल [] यूआरएल = {नया यूआरएल ("जार:" + पथ टोजर + "! /")};' यकीन नहीं क्यों? उम्मीद है कि यह किसी और की मदद करता है। – taylorcressy

+0

अच्छा। हालांकि आप जारफाइल को बंद करना चाहते हैं? कोशिश करें {...} अंत में {jarFile.close(); } –

+0

लिंक मर चुका है। –

6

ऐसा करने के लिए, मैं इस परियोजना स्थान से .class फ़ाइलों के सभी स्कैन करने के लिए सक्षम होना चाहिए (जार/युद्ध: नेस्टेड कक्षाएं, .... javassist एपीआई पर एक नजर डालें या सिर्फ एक फ़ोल्डर)

किसी फ़ोल्डर में सभी फ़ाइलों को स्कैन करना सरल है। एक विकल्प File.listFiles() को File पर कॉल करना है जो फ़ोल्डर को इंगित करता है, फिर परिणामस्वरूप सरणी को पुन: सक्रिय करता है। नेस्टेड फ़ोल्डर्स के पेड़ों को पार करने के लिए, रिकर्सन का उपयोग करें।

एक जेएआर फ़ाइल की फ़ाइलों को स्कैन करना JarFile एपीआई का उपयोग करके किया जा सकता है ... और आपको ट्रैवर्स नेस्टेड "फ़ोल्डरों" के लिए रिकर्स करने की आवश्यकता नहीं है।

इनमें से कोई भी विशेष रूप से जटिल नहीं है। बस जावाडोक पढ़ें और कोडिंग शुरू करें।

8

जार फ़ाइल के अंदर सभी कक्षाएं सूचीबद्ध करें।

public static List getClasseNames(String jarName) { 
    ArrayList classes = new ArrayList(); 

    if (debug) 
     System.out.println("Jar " + jarName); 
    try { 
     JarInputStream jarFile = new JarInputStream(new FileInputStream(
       jarName)); 
     JarEntry jarEntry; 

     while (true) { 
      jarEntry = jarFile.getNextJarEntry(); 
      if (jarEntry == null) { 
       break; 
      } 
      if (jarEntry.getName().endsWith(".class")) { 
       if (debug) 
        System.out.println("Found " 
          + jarEntry.getName().replaceAll("/", "\\.")); 
       classes.add(jarEntry.getName().replaceAll("/", "\\.")); 
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return classes; 
} 
संबंधित मुद्दे