2012-08-08 29 views
6

Trong khi chơi với classloaders tôi đã nhận ngoại lệ sau đây:ClassCastException vì trình nạp lớp?

Exception in thread "main" java.lang.ClassCastException: xxx.Singleton cannot be cast to xxx.Singleton 

Điều này có nghĩa rằng một ví dụ từ một classloader không phải là bột nhôm với một lớp của classloader khác?

Kiểm tra mã của tôi nơi tôi có thể instanciate 3 singletons nhờ bộ nạp lớp, ngay cả với bảo mật "".

public static void main(String[] args) throws Exception { 
     URL basePath = new URL("file:/myMavenPath/target/classes/"); 

    Object instance = getClassInstance(Singleton.class); 
    System.out.println(instance); 
    // 
    Object instance2 = getClassInstance(
      new URLClassLoader(new URL[]{basePath} , null) 
        .loadClass("my.Singleton") 
    ); 
    System.out.println(instance2); 
    // 
    Object instance3 = getClassInstance(
      new URLClassLoader(new URL[]{basePath} , null) 
        .loadClass("my.Singleton") 
    ); 
    System.out.println(instance3); 

    // Only the 1st cast is ok 
    Singleton testCast1 = (Singleton) instance; 
    System.out.println("1st cast ok"); 
    Singleton testCast2 = (Singleton) instance2; 
    System.out.println("2nd cast ok"); 
    Singleton testCast3 = (Singleton) instance3; 
    System.out.println("3rd cast ok"); 
} 

private static Object getClassInstance(Class clazz) throws Exception { 
    Method method = clazz.getMethod("getInstance"); 
    method.setAccessible(true); 
    return method.invoke(null); 
} 


class Singleton { 

    private static final Singleton INSTANCE = new Singleton(); 

    public static Singleton getInstance() { 
     return INSTANCE; 
    } 

    private Singleton() { 
     Exception e = new Exception(); 
     StackTraceElement[] stackTrace = e.getStackTrace(); 
     if (!"<clinit>".equals(stackTrace[1].getMethodName())) { 
      throw new IllegalStateException("You shall not instanciate the Singleton twice !",e); 
     } 
    } 

    public void sayHello() { 
     System.out.println("Hello World ! " + this); 
    } 

} 

Trả lời

3

Bạn không thể bỏ giữa các trình nạp lớp. Danh tính lớp bao gồm tên đầy đủ và trình tải lớp. Kiểm tra danh tính lớp crysishere.

+1

Java có thể chạy nhận dạng Cr ** y ** sis không? –

2

Có, bạn là chính xác.

Điều này thường xảy ra trong các dự án OSGi, do quản lý phụ thuộc kém.

2

Chính xác là như vậy. Bạn không thể sử dụng tính năng truyền giữa các lớp được nạp bởi các trình nạp lớp khác nhau.

This question, "Cast across classloader" có thể làm mọi việc rõ ràng hơn ...

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