2010-03-30 29 views

Trả lời

-1

Vâng, những gì tôi đã làm chỉ đơn giản là liệt kê tất cả các tệp trong đường dẫn lớp. Nó có thể không phải là một giải pháp vinh quang, nhưng nó hoạt động đáng tin cậy và mang lại cho tôi tất cả mọi thứ tôi muốn, và nhiều hơn nữa.

+3

Bạn có thể cung cấp đoạn mã không? theo cách đó, những người khác có thể hưởng lợi từ giải pháp của bạn. thanks – jtzero

+5

@jtzero: Tôi không biết OP được sử dụng, nhưng đối với tôi System.getProperty ("java.class.path") hoạt động tốt. –

+1

điều gì có nghĩa là OP? Nhà điều hành? Lập trình đối tượng? – hyprfrcb

89

Nó không phải là một giải pháp chương trình nhưng bạn có thể chạy

java -verbose:class .... 

và JVM sẽ đổ ra những gì nó có tải, và từ đâu.

[Opened /usr/java/j2sdk1.4.1/jre/lib/rt.jar] 
[Opened /usr/java/j2sdk1.4.1/jre/lib/sunrsasign.jar] 
[Opened /usr/java/j2sdk1.4.1/jre/lib/jsse.jar] 
[Opened /usr/java/j2sdk1.4.1/jre/lib/jce.jar] 
[Opened /usr/java/j2sdk1.4.1/jre/lib/charsets.jar] 
[Loaded java.lang.Object from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] 
[Loaded java.io.Serializable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] 
[Loaded java.lang.Comparable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] 
[Loaded java.lang.CharSequence from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] 
[Loaded java.lang.String from /usr/java/j2sdk1.4.1/jre/lib/rt.jar] 

Xem here để biết thêm chi tiết.

2

Bạn có thể nhận danh sách các lớp được tải thông qua trình nạp lớp nhưng điều này sẽ không bao gồm các lớp bạn chưa tải nhưng nằm trên đường dẫn lớp của bạn.

Để có được TẤT CẢ các lớp học trên đường dẫn lớp học của bạn, bạn phải làm điều gì đó giống như giải pháp thứ hai của mình. Nếu bạn thực sự muốn các lớp học hiện đang được "Nạp" (nói cách khác, các lớp bạn đã tham chiếu, truy cập hoặc khởi tạo) thì bạn nên tinh chỉnh câu hỏi của mình để chỉ ra điều này.

6

Một cách tiếp cận thay thế cho những mô tả ở trên sẽ tạo ra một tác nhân bên ngoài sử dụng java.lang.instrument để tìm ra những lớp được nạp và chạy chương trình của bạn với -javaagent switch:

import java.lang.instrument.ClassFileTransformer; 
import java.lang.instrument.IllegalClassFormatException; 
import java.security.ProtectionDomain; 

public class SimpleTransformer implements ClassFileTransformer { 

    public SimpleTransformer() { 
     super(); 
    } 

    public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) throws IllegalClassFormatException { 
     System.out.println("Loading class: " + className); 
     return bytes; 
    } 
} 

Cách tiếp cận này có lợi ích bổ sung cung cấp cho bạn thông tin về ClassLoader nào đã tải một lớp nhất định.

6

Tôi cũng khuyên bạn nên viết một đại lý -javagent, nhưng sử dụng phương thức getAllLoadedClasses thay vì chuyển đổi bất kỳ lớp nào.

Để đồng bộ hóa với mã khách hàng của bạn (Mã Java thông thường), hãy tạo một ổ cắm và liên lạc với tác nhân qua nó. Sau đó, bạn có thể kích hoạt phương thức "liệt kê tất cả các lớp" bất cứ khi nào bạn cần.

2

Chạy mã của bạn trong một JVM JRockit, sau đó sử dụng JRCMD <PID> print_class_summary

chí đầu ra này lớp học tất cả nạp, một trên mỗi dòng.

3

Một cách nếu bạn đã biết con đường cấp cao nhất gói là sử dụng OpenPojo

final List<PojoClass> pojoClasses = PojoClassFactory.getPojoClassesRecursively("my.package.path", null); 

Sau đó, bạn có thể đi qua danh sách và thực hiện bất kỳ chức năng mà bạn mong muốn.

24

sử dụng thư viện Reflections, thật dễ dàng như:

Reflections reflections = new Reflections("my.pkg", new SubTypesScanner(false)); 

Điều đó sẽ quét tất cả các lớp học trong url/s có chứa gói my.pkg.

  • tham số sai nghĩa là - không loại trừ lớp Object, được loại trừ theo mặc định.
  • trong một số trường hợp (các vùng chứa khác nhau), bạn có thể chuyển classLoader cũng như tham số.

Vì vậy, nhận được tất cả các lớp học được một cách hiệu quả nhận được tất cả các phân nhóm của Object, transitively:.

Set<String> allClasses = 
    reflections.getStore().getSubTypesOf(Object.class.getName()); 

(Cách thông thường reflections.getSubTypesOf(Object.class) sẽ gây ra bốc tất cả lớp vào PermGen và có lẽ sẽ ném OutOfMemoryError bạn don 't muốn làm điều đó ...)

Nếu bạn muốn nhận tất cả trực tiếp các kiểu con của đối tượng (hoặc bất kỳ loại nào khác), mà không nhận được các kiểu con phụ của nó tất cả trong một lần, sử dụng này:

Collection<String> directSubtypes = 
    reflections.getStore().get(SubTypesScanner.class).get(Object.class.getName()); 
+0

Bạn đang sử dụng phiên bản lib phản chiếu nào? Ví dụ này không hoạt động với Reflections 0.9.5. – pablosaraiva

+0

Nevermind, chỉ cần có nó làm việc bằng cách sử dụng phản xạ-0.9.9-RC1-uberjar – pablosaraiva

+1

Bạn chỉ phải trải qua những đau khổ đó là thêm một thư viện khác cho dự án của bạn. Bạn không được phép sử dụng từ "dễ" khi ngôn ngữ được đề cập trong Java. Bạn đã cho tôi hy vọng nghĩ rằng đây là sự phản ánh tiêu chuẩn là một phần của JDK. – ArtOfWarfare

10

Có nhiều câu trả lời cho câu hỏi này, một phần là do câu hỏi mơ hồ - tiêu đề là nói về lớp được nạp bởi JVM, trong khi nội dung của câu hỏi nói "có thể hoặc có thể không được nạp bởi JVM ".

Giả sử rằng OP cần lớp được nạp bởi JVM bởi một classloader nhất định, và chỉ có những lớp học - cần tôi cũng - có là một giải pháp (elaborated here) mà đi như thế này:

import java.net.URL; 
import java.util.Enumeration; 
import java.util.Iterator; 
import java.util.Vector; 

public class CPTest { 

    private static Iterator list(ClassLoader CL) 
     throws NoSuchFieldException, SecurityException, 
     IllegalArgumentException, IllegalAccessException { 
     Class CL_class = CL.getClass(); 
     while (CL_class != java.lang.ClassLoader.class) { 
      CL_class = CL_class.getSuperclass(); 
     } 
     java.lang.reflect.Field ClassLoader_classes_field = CL_class 
       .getDeclaredField("classes"); 
     ClassLoader_classes_field.setAccessible(true); 
     Vector classes = (Vector) ClassLoader_classes_field.get(CL); 
     return classes.iterator(); 
    } 

    public static void main(String args[]) throws Exception { 
     ClassLoader myCL = Thread.currentThread().getContextClassLoader(); 
     while (myCL != null) { 
      System.out.println("ClassLoader: " + myCL); 
      for (Iterator iter = list(myCL); iter.hasNext();) { 
       System.out.println("\t" + iter.next()); 
      } 
      myCL = myCL.getParent(); 
     } 
    } 

} 

Một của những điều gọn gàng về nó là bạn có thể chọn một trình nạp lớp tùy ý mà bạn muốn kiểm tra. Tuy nhiên nó có khả năng phá vỡ nội bộ của lớp thay đổi classloader, vì vậy nó được sử dụng như một công cụ chẩn đoán một lần.

+0

@eis Sự khác nhau giữa việc sử dụng 'Thread.currentThread(). GetContextClassLoader()' so với 'CPTest.class.getClassLoader()' là gì? Có lý do nào mà bạn thích lấy 'ClassLoader' từ đối tượng' Thread' không? –

+0

@MichaelPlautz sự khác biệt là khác là trình tải lớp ngữ cảnh chủ đề và trình còn lại là trình nạp lớp được sử dụng bởi lớp đã cho. Có rất nhiều trình nạp lớp khác nhau được sử dụng bởi java, mà tôi sẽ không xây dựng trong không gian chú thích này. Lý do là giả định rằng mối quan hệ cha mẹ của trình nạp lớp ngữ cảnh chủ đề sẽ bao gồm toàn bộ JVM, trong khi trình nạp lớp có thể không. – eis

+0

Bạn có thể tránh vòng lặp 'while' bằng cách thực hiện' ClassLoader.class.getDeclaredField ("classes") '. – metasim

0

Chương trình này sẽ in tất cả các lớp với đường dẫn vật lý của nó. sử dụng chỉ đơn giản là có thể sao chép này vào bất kỳ JSP nếu bạn cần phải phân tích tải lớp từ bất kỳ máy chủ web/ứng dụng.

import java.lang.reflect.Field; 
import java.util.Vector; 

public class TestMain { 

    public static void main(String[] args) { 
     Field f; 
     try { 
      f = ClassLoader.class.getDeclaredField("classes"); 
      f.setAccessible(true); 
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
      Vector<Class> classes = (Vector<Class>) f.get(classLoader); 

      for(Class cls : classes){ 
       java.net.URL location = cls.getResource('/' + cls.getName().replace('.', 
       '/') + ".class"); 
       System.out.println("<p>"+location +"<p/>"); 
      } 
     } catch (Exception e) { 

      e.printStackTrace(); 
     } 
    } 
} 
Các vấn đề liên quan