Tình huống trong tầm tay không đơn giản như tiêu đề dường như chỉ ra.Làm cách nào để kiểm soát ClassLoader nào sẽ tải lớp học?
Java 1.6_17 chạy qua JWS.
Tôi có một lớp, giả sử MyClass
và một trong các biến thành viên thể hiện của nó là một Loại từ thư viện bên thứ ba không đúng nơi khởi tạo lớp nó cố gắng tải một số lớp riêng của nó bằng Class.forName(String)
. Trong một trong những trường hợp này, nó sẽ tự động gọi: Class.forName("foo/Bar")
. Tên lớp này không tuân theo JLS cho tên nhị phân và cuối cùng dẫn đến một số java.lang.NoClassDefFoundError: foo/Bar
.
Chúng tôi có một tùy chỉnh ClassLoader
mà tôi đã thêm phương pháp khử trùng vào ClassLoader.findClass(String)
và ClassLoader.loadClass(String)
để khắc phục sự cố này.
tôi có thể gọi những thứ như: myCustomClassLoader.findClass("foo/Bar")
Mà sau đó tải các lớp mà không cần bất kỳ vấn đề. Nhưng ngay cả khi tôi tải lớp trước, tôi vẫn nhận được ngoại lệ sau. Điều này là do trong quá trình khởi tạo MyClass
đề cập đến Bar
- mã của chúng kết thúc bằng cách gọi số Class.forName("foo/Bar")
trong một khối tĩnh ở đâu đó. Điều này thực sự sẽ là OK nếu ClassLoader nó đã cố gắng sử dụng là bộ nạp lớp tùy chỉnh của tôi. Nhưng không phải vậy. Đó là com.sun.jnlp.JNLPClassLoader
mà không làm vệ sinh như vậy, do đó vấn đề của tôi.
Tôi đã đảm bảo rằng Thread.currentThread().getContextClassLoader()
được đặt thành trình tải lớp tùy chỉnh của tôi. Nhưng điều này (như bạn biết) không có hiệu lực. Tôi thậm chí thiết lập nó như là điều đầu tiên tôi làm trong main()
do một số công cụ tôi đọc và vẫn còn, MyClass.class.getClassLoader()
- là JNLPClassLoader. Nếu tôi có thể ép buộc nó không phải là JNLPClassLoader và sử dụng của tôi thay vào đó, vấn đề được giải quyết.
Làm cách nào để kiểm soát ClassLoader nào được sử dụng để tải lớp học thông qua lời gọi Class.forName tĩnh ("foo/Bar") của họ trong quá trình khởi tạo lớp? Tôi tin rằng nếu tôi có thể buộc MyClass.class.getClassLoader()
trả lại trình tải lớp tùy chỉnh của tôi, thì sự cố của tôi sẽ được giải quyết.
Tôi đang mở cho các tùy chọn khác nếu có ai đó có ý tưởng.
TL; DR: Giúp tôi buộc tất cả các cuộc gọi Class.forName(String)
trong thư viện của bên thứ ba được tham chiếu bởi MyClass
- để sử dụng trình nạp lớp mà tôi chọn.
* "từ thư viện bên thứ ba sai lệch" * Chiến lược tốt nhất cuối cùng là thay thế API đó. –
@AndrewThompson Nó có thể đến đó. Tôi hy vọng nó không. Vì vậy, nếu bất cứ ai có bất kỳ ý tưởng - Tôi là tất cả tai! –
Tôi đã làm một cái gì đó tương tự bằng cách tạo một lớp bootstrap và sử dụng một URLClassLoader để tải tất cả các thư viện bên ngoài của chúng ta từ đó. Họ không ở trong classpath khi lớp boostrap khởi chạy, do đó, trình nạp lớp duy nhất mà họ thấy là lớp tùy chỉnh. Không phải là một câu trả lời bởi vì tôi không có ý tưởng nếu nó sẽ làm việc với JWS. Chúng tôi đã làm nó để tải thư viện plugin vào thời gian chạy. – Thomas