Như bạn có thể biết và câu trả lời ở trên cũng làm rõ rằng các đối tượng đồng hành được dịch sang các lớp và lớp khai báo chúng giữ một tham chiếu tĩnh đến đối tượng của lớp đồng hành, một số thứ như sau:
public static final MyClass.Companion Companion = new MyClass.Companion(null);
Bây giờ câu hỏi
Các đối tượng đồng hành có còn trong bộ nhớ cho vòng đời của ứng dụng không
bởi vì lớp khai báo giữ một static
tham chiếu đến lớp đồng hành, câu hỏi giảm thời gian sống của static
các trường trong jvm class
và câu trả lời nằm trong thông số JVM , nhưng thông số này hơi khô khan trong lời giải thích nên tôi thêm một số đoạn trích từ cuốn sách Bên trong Máy ảo Java .
Như trong ví dụ của bạn, giả sử chúng ta class
không có gì ngoài đối tượng đồng hành duy nhất.
Câu hỏi đầu tiên là khi một đối tượng của lớp đồng hành sẽ được tạo ra? hoặc khi static
các trường được khởi tạo?
văn bản có liên quan từ cuốn sách . (đối với bối cảnh cuốn sách đang nói về thủ tục tải lớp)
Khởi tạo
Bước cuối cùng cần thiết để sẵn sàng một lớp hoặc giao diện cho lần sử dụng đầu tiên của nó là khởi tạo, quá trình thiết lập các biến lớp thành các giá trị ban đầu thích hợp của chúng. Như được sử dụng ở đây, giá trị ban đầu "phù hợp" là giá trị bắt đầu mong muốn của lập trình viên cho một biến lớp. Một giá trị ban đầu thích hợp tương phản với giá trị ban đầu mặc định được cung cấp cho các biến lớp trong quá trình chuẩn bị. Như đã mô tả ở trên, máy ảo chỉ định các giá trị mặc định chỉ dựa trên mỗi loại biến. Ngược lại, các giá trị ban đầu thích hợp dựa trên một số kế hoạch tổng thể chỉ được biết đến bởi người lập trình. Trong mã Java, một giá trị ban đầu thích hợp được chỉ định thông qua bộ khởi tạo biến lớp hoặc bộ khởi tạo tĩnh.
Vì vậy, chúng ta biết rằng một khi MyClass
được tải và khởi tạo, đối tượng của lớp đồng hành sẽ được tạo.
nhưng điều gì sẽ khiến JVM tải MyClass
?
Đặc tả máy ảo Java cho phép triển khai linh hoạt trong thời gian tải và liên kết giao diện lớp và giao diện, nhưng xác định nghiêm ngặt thời gian khởi tạo. Tất cả các cài đặt phải khởi tạo mỗi lớp và giao diện trong lần sử dụng đầu tiên. Một hoạt động sử dụng của một lớp là:
Việc gọi hàm tạo trên một thể hiện mới của lớp
Việc tạo ra một mảng có lớp là một kiểu phần tử của nó
Yêu cầu của một phương thức được khai báo bởi lớp (không được kế thừa từ một siêu lớp)
4 Việc sử dụng hoặc gán một trường được khai báo bởi lớp (không được kế thừa từ siêu lớp hoặc siêu giao diện), ngoại trừ các trường cả tĩnh và cuối cùng và được khởi tạo bởi một biểu thức hằng số thời gian biên dịch
Vì vậy, theo điểm thứ 4 khi bạn làm MyClass.foo()
từ kotlin hoặc MyClass.Companion.foo()
tại thời điểm MyClass
này sẽ được tải và sẵn sàng. (Có lẽ là rất sớm)
Xin lưu ý rằng tại thời điểm này không có đối tượng MyClass
tồn tại, đó là chúng ta chưa sử dụng biểu thức MyClass()
.
Điều này có nghĩa là static
các trường sẽ vẫn còn trong bộ nhớ miễn là ứng dụng đang chạy?
Chúng có thể là rác được thu thập nếu loại khai báo được tải, trong trường hợp của chúng ta nếu JVM hoặc ART (trên Android) dỡ tải MyClass
thì có khả năng đối tượng đồng hành sẽ được thu gom Rác.
JVM Spec đã nói sau đây về việc dỡ lớp
Việc thực hiện ngôn ngữ lập trình Java có thể dỡ bỏ các lớp.
Một lớp hoặc giao diện có thể được dỡ tải nếu và chỉ khi trình nạp lớp xác định của nó có thể được thu hồi bởi trình thu gom rác như đã thảo luận trong §12.6.
Các lớp và giao diện được tải bởi trình tải bootstrap có thể không được tải.
Trong lớp thực tế, việc dỡ tải gần như (tôi đã nói gần như) không bao giờ xảy ra, vì vậy , các đối tượng đồng hành sẽ vẫn còn trong bộ nhớ cho vòng đời của ứng dụng .