2012-06-13 14 views
49

Bir Java uygulamasının yapısını tarayacak ve bazı anlamlı bilgiler sağlayacak bir Java aracı oluşturmaya çalışıyorum. Bunu yapmak için, tüm .class dosyalarını proje konumundan (JAR/WAR veya sadece bir klasör) tarayabilmem ve yöntemlerini okumak için yansımayı kullanabilmem gerekir. Bu imkansız olduğu kanıtlıyor.Sınıflar çalışma zamanında bir klasörden veya JAR'den nasıl yüklenir?

URLClassloader temelli bir dizini/dizinden belirli sınıfları yüklememe izin veren birçok çözüm bulabilirim, ancak sınıf adı veya paket yapısı hakkında bilgi sahibi olmadan sınıfları yüklememe izin vermez.

DÜZENLEMEK: Sanırım bunu kötü derken. Sorunum, tüm sınıf dosyalarını alamıyorum, yineleme vb. Ile bunu yapabilirim ve bunları düzgün bir şekilde bulabilirim. Sorunum, her sınıf dosyası için bir Sınıf nesnesi ediniyor.

+1

Tam olarak nitelenmiş adını göz ardı ederek bir sınıfı nasıl yüklersiniz? Bunun mümkün olduğunu düşünmüyorum. –

+4

Aşağıdaki cevaplar sınıf dosyalarını bulmanızı sağlar, ancak projenizin büyüklüğüne bağlı olarak, [asm] (http://asm.ow2.org/) veya [javassist] (http: //) kullanmaya değer olabilir. www.csg.ci.iu-tokyo.ac.jp/~chiba/javassist/). Bunlar, hepsini belleğe yüklemeden sınıfları analiz etmenize izin verecektir. –

cevap

87

Aşağıdaki kod, JAR dosyasındaki tüm sınıfları yükler. Sınıflar hakkında hiçbir şey bilmeye gerek yoktur. Sınıfların isimleri JarEntry'den çıkarılır.

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); 

} 

düzenleme: Yukarıda Yorum önerilen olarak

, javassist da bir ihtimal olacaktır. yere while döngüsünde önce ClassPool başlat Yukarıdaki kodu oluşturmak ve bunun yerine sınıf yükleyicisi ile sınıf yükleme, bir CtClass nesnesi oluşturabilirsiniz: ctClass itibaren

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

, tüm yöntemler, alanlar alabilirsiniz https://jboss-javassist.github.io/javassist/html/index.html

+1

Eski bir gönderi getirdiğim için üzgünüm (bu cevap için teşekkür ederim btw, benim için çalışıyor). Ancak, 'yeni URL (" jar: file: "+ pathToJar +"!/")' 'ClassNotFoundException''na neden oldu. Benim için çalışma neydi: 'URL [] urls = {new URL (" jar: "+ pathToJar +"!/")}; Neden olmadığından emin değil misiniz? Umarım başkasına yardım eder. – taylorcressy

+0

Güzel. Yine de jarFile'ı kapatmak isteyebilir misin? {...} son olarak {jarFile.close(); } –

+0

Bağlantı kesildi. –

6

ben proje konumdan .class tüm dosyaları taramak gerekiyor bunu yapmak için (JAR/SAVAŞ:, iç içe sınıflar, .... javassist API bir göz atın veya sadece bir klasör)

Klasördeki tüm dosyaların taranması basit. Bir seçenek File.listFiles()'u klasöre işaret eden File numaralı telefondan aramak ve sonuçta oluşan diziyi yinelemektir. İç içe geçmiş klasörlerin ağaçlarını taşımak için özyinelemeyi kullanın.

Bir JAR dosyasının dosyalarının taranması JarFile API ... kullanılarak yapılabilir ve iç içe geçmiş "klasörler" i geçmek için tekrarlamanız gerekmez.

Bunlardan hiçbiri özellikle karmaşık değildir. Sadece javadoc'u oku ve kodlamayı başlat.

8

Liste Kavanoz dosyası içindeki tüm sınıflar.

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; 
} 
İlgili konular