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


8

Trong Kotlin, bạn có thể tạo một singleton bằng cách sử dụng một đối tượng đồng hành:

class MyClass {
   companion object {
        fun doSomething() {

        }
    }
}

Theo các tài liệu của Kotlin, nó tuyên bố:

Lưu ý rằng, mặc dù các thành viên của các đối tượng đồng hành trông giống như các thành viên tĩnh trong các ngôn ngữ khác, trong thời gian chạy, chúng vẫn là các thành viên thể hiện của các đối tượng thực ...

https://kotlinlang.org/docs/reference/object-declarations.html

Điều này có nghĩa là sau khi sử dụng một hàm trong đối tượng đồng hành, thể hiện của lớp (MyClass) vẫn còn trong bộ nhớ cho toàn bộ vòng đời của ứng dụng? Có cách nào trong Android Studio để kiểm tra xem đây có phải là trường hợp không?


Bạn có thể cung cấp liên kết đến tài liệu mà bạn giới thiệu không?
Sonu Sanjeev

Liên kết thêm vào bài viết.
AndroidDev

Câu trả lời:


6

ví dụ của lớp (MyClass) vẫn còn trong bộ nhớ cho toàn bộ vòng đời của ứng dụng ?

Đối tượng đồng hành trong JVM

ở kotlin

class MyClass {
   companion object {
        fun doSomething() {

        }
    }
}

MyClass (Kotlin) được chuyển đổi trong JVM

public final class MyClass {
   public static final MyClass.Companion Companion = new MyClass.Companion(null);

   public static final class Companion {
      public final void doSomething() {
      }

      private Companion() {
      }

      public Companion() {
         this();
      }
   }
}

Như mã trên, companion objectđược khai báo là Companionlớp trong JVM và nó được tạo như là statictrường bên trong MyClasslớp. Do đó, không được thu thập bởi gc. Vì vậy, bộ nhớ của đối tượng (Đồng hành) vẫn còn trong ProcessLifecycle. static final objectkhông được phát hành trong trường hợp bình thường.

Tóm lại, nếu được đề cập đến MyClass.Companionthể hiện trong ứng dụng, thì thể hiện đó sẽ không được thu gom rác. (trên Trình tải lớp chung).

* Nếu không được đề cập đến MyClass.Companiontrong ứng dụng, nó có thể bị xóa bởi tính năng thu hẹp mã .

Có cách nào trong Android Studio để kiểm tra xem đây có phải là trường hợp không?

Bạn có thể xem qua studio android> profiler> Heap dump.

Tài liệu tham khảo


Câu trả lời tốt đẹp! Nhưng làm thế nào bạn tìm thấy mã "MyClass (Kotlin) được chuyển đổi trong JVM" ??
Astha

0

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 statictham chiếu đến lớp đồng hành, câu hỏi giảm thời gian sống của staticcác trường trong jvm classvà 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 classkhô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 staticcá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à:

  1. Việc gọi hàm tạo trên một thể hiện mới của lớp

  2. Việc tạo ra một mảng có lớp là một kiểu phần tử của nó

  3. 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 MyClassnà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 MyClasstồ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à staticcá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 MyClassthì 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 .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.