Tôi muốn nhận danh sách tất cả các lớp thuộc về một gói nhất định cũng như tất cả các con của chúng. Các lớp có thể hoặc có thể chưa được tải trong JVM.Java - Nhận danh sách tất cả các Lớp được tải trong JVM
Trả lời
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.
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.
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.
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.
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.
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.
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.
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());
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
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
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
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.
@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? –
@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
Bạn có thể tránh vòng lặp 'while' bằng cách thực hiện' ClassLoader.class.getDeclaredField ("classes") '. – metasim
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();
}
}
}
- 1. Nhận danh sách tất cả các lớp đang được tải trong một cá thể JVM cụ thể
- 2. Lấy danh sách tất cả các trình nạp lớp trong một JVM
- 3. android dexclassloader lấy danh sách tất cả các lớp
- 4. Danh sách tất cả các lớp miền trong Grails
- 5. LINQ: Nhận danh sách tất cả các bảng trong DataContext
- 6. Cách nhận tất cả các mục khác trong danh sách
- 7. Lấy danh sách tất cả các chủ đề hiện đang chạy trong Java
- 8. Nhận danh sách tất cả các lần bấm với Git
- 9. In Tất cả Flags JVM
- 10. JavaScript Nhận tất cả các tập lệnh được tải
- 11. Java: lập trình xác định tất cả tên gói được tải trên đường dẫn lớp
- 12. Sử dụng Google Reflections để xem danh sách tất cả các lớp - nhưng java. * Có vẻ thiếu
- 13. Nhận danh sách tất cả các nút cây (ở tất cả các cấp) trong Điều khiển TreeView
- 14. truy xuất danh sách tất cả các nhãn trong blogger
- 15. Nhận tất cả các kết hợp các cặp từ một danh sách trong Ruby
- 16. Thu hẹp tất cả các phần tử trong danh sách
- 17. Định dạng tất cả các phần tử trong danh sách
- 18. danh sách PHP tất cả các file trong thư mục
- 19. Xóa tất cả các mục nhập trong danh sách Redis
- 20. JQuery nhận được tất cả dữ liệu thuộc tính từ một danh sách
- 21. Haskell: hiển thị/nhận danh sách tất cả các chức năng do người dùng định nghĩa
- 22. Visual Studio 2012: Danh sách tất cả các phương thức trong lớp
- 23. Làm cách nào để có danh sách tất cả các loại được nạp trong C#?
- 24. Danh sách tất cả các máy chủ trên mạng LAN
- 25. Nhận một danh sách của tất cả các buổi hoạt động trong ASP.NET
- 26. Lấy tên của tất cả các lớp Java được khai báo trong một gói
- 27. Nhận giá trị tối đa từ tất cả các ma trận trong danh sách
- 28. Xóa tất cả các mục từ một danh sách
- 29. Danh sách tất cả các cam kết git?
- 30. Nhận danh sách tất cả các tham số chức năng từ bên trong hàm
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
@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. –
điều gì có nghĩa là OP? Nhà điều hành? Lập trình đối tượng? – hyprfrcb