Câu hỏi Tôi nên cung cấp ClassLoader nào cho Proxy.newProxyInstance (…)?


Tôi đã đọc tài liệu, nhưng tôi vẫn không hiểu bộ nạp lớp nào mà tôi nên cung cấp làm đối số. Tôi đã thử một vài tùy chọn, nhưng điều này dường như không ảnh hưởng đến việc biên dịch hoặc hành vi của proxy. Đó là một chút đáng lo ngại rằng tôi có thể vượt qua bất cứ điều gì như là đối số bộ nạp lớp, bao gồm nullvà mã vẫn hoạt động tốt. Bất cứ ai có thể giải thích điều này, và cho tôi biết những loại lỗi có thể phát sinh nếu tôi cung cấp một đối số xấu cho bộ nạp lớp? Tôi nên thêm rằng tôi không thực sự có một ý tưởng trực quan mạnh mẽ về những gì một trình nạp lớp là, trong Java hoặc nói chung.


9
2018-03-29 23:09


gốc




Các câu trả lời:


Bất kỳ lớp nào cần phải có một trình nạp lớp, do đó chúng ta phải cung cấp một lớp ở đây.

Phần quan trọng là cái này (trong tài liệu cho getProxyClass()):

Tất cả các loại giao diện phải được hiển thị theo tên thông qua trình nạp lớp được chỉ định. Nói cách khác,   cho lớp trình nạp cl và mọi giao diện i, biểu thức sau phải đúng:

Class.forName(i.getName(), false, cl) == i

Vì vậy, bạn có thể sử dụng bất kỳ trình nạp lớp nào mà một (hoặc nhiều) trình nạp lớp cha của nó đã định nghĩa các giao diện đã cho.

Nếu null hoạt động trong trường hợp của bạn, tôi cho rằng các giao diện của bạn cũng có null bộ nạp lớp (bộ tải khởi động) - thì không quan trọng bạn đang sử dụng trình nạp lớp nào. Nếu bạn phải tạo proxy từ các giao diện mà bạn không biết, chỉ cần lấy trình nạp lớp của giao diện đầu tiên được đưa ra và hy vọng người gọi của bạn không làm điều gì lạ.

Tại sao nó là cần thiết?

Bạn có thể tưởng tượng nó như thế này:

  • Các getProxyClass() phương thức tạo ra (nếu nó chưa tồn tại) một số bytecode cho một lớp mới thực hiện tất cả các phương thức của tất cả các giao diện của bạn (mỗi người trong số họ chỉ đơn giản là chuyển tiếp cuộc gọi đến của bạn InvocationHandler).
  • Sau đó, nó chuyển bytecode này sang defineClass phương thức của trình nạp lớp mà bạn đã chỉ định.
  • Trong bytecode này, tất cả các giao diện của bạn được tham chiếu theo tên, và VM bây giờ sử dụng trích dẫn forName gọi để giải quyết các giao diện này.

Chúng ta có thể đã thực hiện điều này getProxyClass theo cách này trong Java tinh khiết mà không có bất kỳ phép ảo VM nào, nhưng chúng ta sẽ cần phải tạo một trình nạp lớp mới (với một lớp được chỉ định làm cha mẹ) cho nó thay vì có thể sử dụng lại một trình sẵn có.

Trong thực tế có thể không có một bytecode thực tế cho lớp tổng hợp này, vì VM có thể sử dụng ma thuật bên trong của nó ở đây :-)


6
2018-03-29 23:46



Cảm ơn, tôi vẫn không có trực giác cho những gì một trình nạp lớp thực hiện. Bạn có thể đề cập một chút về điều này? Tôi vẫn gặp khó khăn trong việc hiểu tại sao một trình nạp lớp rỗng có thể hoạt động nếu trình nạp lớp chịu trách nhiệm thực hiện bất kỳ điều gì đáng kể. Có lẽ một ví dụ đồ chơi mà một trình nạp lớp không chính xác được đưa ra? - jonderry
Các null classloader là "bootstrap classloader", trình nạp lớp tải các lớp lõi (như Class, Object, ClassLoader). Nó được thực thi nguyên bản bởi VM và không có đối tượng ClassLoader. (Nó được sử dụng bởi Class.forName nếu bạn cho null như ClassLoader đối số, ví dụ). (Ví dụ sẽ đến sau.) - Paŭlo Ebermann