Tôi đang gặp sự cố thực sự lạ trong ứng dụng Android. Sau một thời điểm nhất định (xung quanh khi hoạt động chính bắt đầu và một đoạn được hiển thị), FinalizerDaemon chỉ dừng các đối tượng xử lý và thùng rác sẽ chồng chất lên. Nhìn vào kết xuất chuỗi, dường như bị kẹt trên ReferenceQueue.remove()
:Android FinalizerDaemon treo lên
"[email protected]" daemon prio=5 waiting
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Object.java:-1)
at java.lang.Object.wait(Object.java:423)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:101)
- locked <0x1173> (a java.lang.ref.ReferenceQueue)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:72)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:185)
at java.lang.Thread.run(Thread.java:818)
Tuy nhiên, hàng đợi không trống. Nếu tôi đổ đống sau khi sử dụng ứng dụng trong một thời gian, hàng đợi có nghĩa là hàng ngàn mục dài. Cấu trúc dữ liệu cũng không bị hỏng:
Dumping lại sau khi phân bổ và thu gom rác thêm một số cho thấy người đứng đầu hàng đợi là cùng một trường hợp Matrix như trước.
Bây giờ, tôi nhận thấy điều này vì tôi đang giữ lại một số đối tượng C++ cần được phát hành tại một số điểm. Trong khi tôi nghi ngờ rằng một finalizer gọi vào JNI chức năng và làm một cái gì đó ngu ngốc bên C++ bằng cách nào đó có thể phá vỡ nó, tất cả các bản ghi của tôi chỉ ra rằng tất cả các finalizers đang chạy tốt và trở về mà không ném bất cứ điều gì cho đến khi họ chỉ ngẫu nhiên ngừng nhận được gọi. Ngoài ra, nó không thực sự có thể cho một cuộc gọi hoàn thành để phá vỡ Daemon, thiếu segfaulting toàn bộ ứng dụng hoặc một cái gì đó, kể từ khi Watchdog là vụ phải xử lý finalizers chạy quá lâu và ném một ngoại lệ.
Tôi đã thử một cách rõ ràng System.runFinalization()
và tất cả những gì nó làm là treo chủ đề chính mãi mãi, chờ đợi cho daemon không bao giờ chạy.
Bất kỳ ý tưởng nào về điều này có thể xảy ra?
Nhìn vào https://android.googlesource.com/platform/libcore/+/marshmallow-mr1-release/luni/src/main/java/java/lang/ref/ReferenceQueue.java, nó đang chờ đợi mãi mãi cho một cái gì đó để loại bỏ. Giả sử nó bị mắc kẹt ở đây (so với chạy rất nhanh và bạn chỉ xảy ra để bắt nó ở đây), điều đó sẽ gợi ý rằng các tài liệu tham khảo mới không được thêm vào. Nếu bạn thấy 'đầu! = Null' trên hàng đợi đó, thì nó sẽ xuất hiện bất cứ điều gì GC đang làm để thêm tham chiếu là không báo hiệu hàng đợi. Phiên bản Android nào? – fadden
@fadden Tôi đã chỉnh sửa câu hỏi. Lấy các khối đống lặp lại cho thấy rằng phần đầu của hàng đợi không phải là null và nó không di chuyển từ cùng một đối tượng. Không có bản ghi nào của tôi trong finalizers in hoặc sau thời điểm khi nó dường như gặp khó khăn. Nó sẽ là khá khó mà tôi chỉ ngẫu nhiên bắt nó vào chờ đợi mỗi khi tôi cố gắng, trong các phần khác nhau của ứng dụng và trên các thiết bị khác nhau. Tôi đã sao chép nó trên Nexus 4 (5.1) và bộ giả lập x86 6.0, và tôi có lý do để nghi ngờ rằng nó xảy ra trên một tá thiết bị thử nghiệm khác mà tôi chưa nhận được để kết nối với Android Studio của mình. – IvoDankolov
Có vẻ như ReferenceQueue không hoạt động chính xác. Hoặc đây là một vấn đề phổ biến mà không ai đã xảy ra để thông báo (không), hoặc ứng dụng của bạn đã vô tình nhét những thứ lên. Có lẽ một số mã nguồn gốc đã viết bên ngoài ranh giới đối tượng và chuyển vào một khóa màn hình, vì vậy 'notify()' không còn hoạt động nữa? Bạn có thể thử đính kèm một trình gỡ lỗi và tự tiến hoặc xóa 'đầu' để xem nó có bắt đầu hoạt động khi bạn thả mục nhập hiện tại (và sau đó tạo thêm một số rác để khiến hàng đợi báo hiệu). – fadden