2016-05-03 19 views
17

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: FinalizerDaemon instance showing a non-empty ReferenceQueue

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?

+0

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

+0

@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

+0

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

Trả lời

1

Tôi tin rằng điều này phải làm với một số đối tượng là resurrected trong phương thức hoàn thiện của chúng.

Tôi sẽ trích dẫn một đoạn từ question này.

Chuỗi kết thúc chạy để bộ sưu tập rác hoạt động để làm sạch lên tài nguyên được liên kết với đối tượng. Nếu tôi nhìn thấy nó một cách cẩn thận, trình phân tích không thể lấy khóa cho đối tượng này: java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:118) vì đối tượng java đang chạy phương thức, do đó, thread finalizer bị khóa cho đến khi đối tượng đó kết thúc với nhiệm vụ hiện tại của nó.

Có thể đó là tình huống của bạn.

+0

Tôi e rằng đây không phải là trường hợp. Những gì Threaddump nói là chỉ FinalizerDaemon đang chờ đợi mãi mãi cho một đối tượng có sẵn trên ReferenceQueue. Nhưng tại sao không có đồ vật nào đến? –

+0

Nếu bạn đúng và tôi đang xem một cái gì đó: Bạn có thể nói chính xác đối tượng java nào đang chạy một phương thức khóa trình hoàn chỉnh không? –

+0

Đây là một Threadump: https://code.google.com/p/android/issues/attachmentText?id=215906&aid=2159060001000&name=threads_report.txt&token=ABZ6GAf2Zh1q6ogUdf33PqBXMILxOHjAjA%3A1469110397989 –

Các vấn đề liên quan