2010-08-08 16 views
5

Tôi đang cố gắng xác định Trình nạp lớp tùy chỉnh.ContextClassLoader không hooking

public class ExampleLoader extends ClassLoader 
{ 
    public Class<?> findClass(String name) throws ClassNotFoundException 
    { 
     System.out.println("This never gets printed"); 
     return super.findClass(name); 
    } 

    public Class<?> loadClass(String name, boolean b) 
     throws ClassNotFoundException 
    { 
     System.out.println("This never gets printed"); 
     return super.loadClass(name, b); 
    } 
} 

Và tất nhiên mã của tôi để kiểm tra nó:

public class Tester 
{ 
    public static void main(String[] args) 
    { 
     Thread t = new FooThread(); 
     t.setContextClassLoader(new ExampleLoader()); 
     t.start(); 
    } 
} 

class FooThread extends Thread 
{ 
    public void run() 
    { 
     new RandomClass(); 
    } 
} 

Vấn đề là dòng của tôi không bao giờ được in ra. Rõ ràng tôi đang thiếu một cái gì đó.

Trả lời

6

Điều này liên quan đến bug 4868493. Dưới đây là một trích dẫn liên quan:

Đáng tiếc là tài liệu cho getContextClassLoadersetContextClassLoader có thể dẫn người ta đến kết luận rằng mã nộp của nên làm việc như mong đợi.

Tuy nhiên, có một nguyên tắc cơ bản trong lớp tải - không có lớp có thể bao giờ tự động tải một lớp học mà là "hạ lưu", ví dụ: không có thể được nạp trực tiếp bằng mà lớp ClassLoader hay một trong những tổ tiên của nó ClassLoaders.

Điều này được mô tả ở một số địa điểm. Ví dụ: thiền định trên giấy trắng có sẵn tại đây: http://www.javageeks.com/Papers/ClassForName/index.html để đạt được chứng ngộ.

Điểm quan trọng có vẻ là trình tải lớp ngữ cảnh không được sử dụng tự động bởi ngôn ngữ Java. . Nó chỉ là một nơi thông thường để lưu bộ nạp lớp ngữ cảnh để các lớp khác có thể sử dụng nó với 3-argument form of Class.forName.

Các spec cho Thread.getContextClassLoaderThread.setContextClassLoader cần được làm rõ, và ý nghĩa của "bối cảnh lớp loader" nên được làm rõ. Phân loại lại dưới dạng lỗi tài liệu.

Thông số chưa được làm rõ.

Để có được nó để làm việc gì ban đầu bạn muốn, thay new RandomClass() bởi

Class.forName(RandomClass.class.getName(), 
       true, 
       getContextClassLoader()).newInstance(); 

in này, contradictorily, như sau:

This never gets printed
+0

Ra khỏi tò mò, làm thế nào để các ứng dụng như Tomcat làm cho công việc này? Sự hiểu biết của tôi là tất cả các ứng dụng web tomcat chạy từ bên trong một jvm dùng chung, nhưng khi chúng sử dụng các lớp, các định nghĩa lớp đến từ các cuộc chiến tranh tương ứng của chúng. Bất kỳ ý tưởng làm thế nào họ đạt được điều này? – Jim

+2

Chúng sử dụng 'ClassLoader # loadClass()'. Ví dụ 'ClassLoader' được lưu trữ và truyền xung quanh trong chuỗi theo cách này. Một điểm khởi đầu tốt để tìm trong mã nguồn là 'org.apache.catalina.core.DefaultInstanceManager'. – BalusC

0

Thông thường, tất cả classloaders trong một JVM được tổ chức trong một phân cấp như vậy mà mọi trình nạp lớp (ngoại trừ trình nạp lớp nguyên thủy khởi động toàn bộ JVM) có một phụ huynh đơn. Khi được yêu cầu tải một lớp, mọi trình nạp lớp tuân thủ được mong đợi sẽ ủy nhiệm tải cho cha mẹ của nó trước và cố gắng xác định lớp chỉ khi cha mẹ không thành công.

Điều tương tự cũng xảy ra trong trường hợp của bạn. "RandomClass" sẽ được tải, ContextClassLoader ủy nhiệm cho phụ huynh của nó như vậy. Và một trong những trình nạp lớp cha mẹ đã có thể tải "RandomClass" (RandomClass là trong classpath của phụ huynh). Vì lý do này, SOP của bạn không hiển thị.

tham khảo sau bài viết ít tuổi nhưng tốt:

http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html?page=1

Các vấn đề liên quan