Làm thế nào để xử lý: java.util.conc hiện.TimeoutException: android.os.BinderProxy.finalize () đã hết thời gian sau 10 giây lỗi?


166

Chúng tôi đang thấy một số TimeoutExceptionstrong GcWatcher.finalize, BinderProxy.finalize, và PlainSocketImpl.finalize. 90 +% trong số đó xảy ra trên Android 4.3. Chúng tôi đang nhận được báo cáo về điều này từ Crittercism từ người dùng trong lĩnh vực này.

nhập mô tả hình ảnh ở đây

Lỗi là một biến thể của: " com.android.internal.BinderInternal$GcWatcher.finalize() timed out after 10 seconds"

java.util.concurrent.TimeoutException: android.os.BinderProxy.finalize() timed out after 10 seconds
at android.os.BinderProxy.destroy(Native Method)
at android.os.BinderProxy.finalize(Binder.java:459)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:187)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:170)
at java.lang.Thread.run(Thread.java:841)

Cho đến nay chúng tôi không có bất kỳ may mắn nào tái tạo vấn đề trong nhà hoặc tìm ra những gì có thể gây ra nó.

Bất kỳ ý tưởng những gì có thể gây ra điều này? Bất kỳ ý tưởng làm thế nào để gỡ lỗi này và tìm ra phần nào của ứng dụng gây ra điều này? Bất cứ điều gì làm sáng tỏ vấn đề giúp.

Thêm Stacktraces:

1   android.os.BinderProxy.destroy  
2   android.os.BinderProxy.finalize Binder.java, line 482
3   java.lang.Daemons$FinalizerDaemon.doFinalize    Daemons.java, line 187
4   java.lang.Daemons$FinalizerDaemon.run   Daemons.java, line 170
5   java.lang.Thread.run    Thread.java, line 841  

2

1   java.lang.Object.wait   
2   java.lang.Object.wait   Object.java, line 401
3   java.lang.ref.ReferenceQueue.remove ReferenceQueue.java, line 102
4   java.lang.ref.ReferenceQueue.remove ReferenceQueue.java, line 73
5   java.lang.Daemons$FinalizerDaemon.run   Daemons.java, line 170
6   java.lang.Thread.run

3

1   java.util.HashMap.newKeyIterator    HashMap.java, line 907
2   java.util.HashMap$KeySet.iterator   HashMap.java, line 913
3   java.util.HashSet.iterator  HashSet.java, line 161
4   java.util.concurrent.ThreadPoolExecutor.interruptIdleWorkers    ThreadPoolExecutor.java, line 755
5   java.util.concurrent.ThreadPoolExecutor.interruptIdleWorkers    ThreadPoolExecutor.java, line 778
6   java.util.concurrent.ThreadPoolExecutor.shutdown    ThreadPoolExecutor.java, line 1357
7   java.util.concurrent.ThreadPoolExecutor.finalize    ThreadPoolExecutor.java, line 1443
8   java.lang.Daemons$FinalizerDaemon.doFinalize    Daemons.java, line 187
9   java.lang.Daemons$FinalizerDaemon.run   Daemons.java, line 170
10  java.lang.Thread.run

4

1   com.android.internal.os.BinderInternal$GcWatcher.finalize   BinderInternal.java, line 47
2   java.lang.Daemons$FinalizerDaemon.doFinalize    Daemons.java, line 187
3   java.lang.Daemons$FinalizerDaemon.run   Daemons.java, line 170
4   java.lang.Thread.run

2
Đừng bận tâm, tìm thấy nó bugzilla.mozilla.org/show_orms.cgi?id=864102 Tôi cũng có thể xác nhận đang ảnh hưởng đến các ứng dụng của chúng tôi, nó có mùi giống như sự cố của Google Play Services
eveliotc

Dòng mã lỗi được đưa ra đã được giới thiệu Phiên bản 4.3_r1, được phát hành vào ngày 5 tháng 6 năm 2013. Có thể vấn đề đang xảy ra kể từ đó.
edubriguenti

Phiên bản Android 4.2.2 cũng bắt đầu ném ngoại lệ này để có thể bản cập nhật google play là nguồn.
JWqvist

@EvelioTarazona Tôi có nó trong một số ứng dụng không sử dụng dịch vụ vui chơi
ligi

@ligi có phải là cùng dấu vết cho bạn không?
eveliotc

Câu trả lời:


220

Công bố đầy đủ - Tôi là tác giả của bài nói chuyện được đề cập trước đây trong TLV DroidCon.

Tôi đã có cơ hội kiểm tra vấn đề này trên nhiều ứng dụng Android và thảo luận vấn đề này với các nhà phát triển khác gặp phải nó - và tất cả chúng ta đều có cùng một điểm: vấn đề này không thể tránh được, chỉ giảm thiểu.

Tôi đã xem xét kỹ hơn về việc triển khai mặc định mã trình thu gom Rác Android, để hiểu rõ hơn lý do tại sao ngoại lệ này bị ném và về nguyên nhân có thể là gì. Tôi thậm chí đã tìm thấy một nguyên nhân gốc rễ có thể trong quá trình thử nghiệm.

Nguyên nhân của vấn đề là tại thời điểm một thiết bị "Đi ngủ" - điều này có nghĩa là HĐH đã quyết định giảm mức tiêu thụ pin bằng cách dừng hầu hết các quy trình của Người dùng trong một thời gian và tắt Màn hình, giảm chu kỳ CPU , v.v ... Cách thức này được thực hiện - là ở cấp độ hệ thống Linux, nơi các quy trình được Tạm dừng giữa chừng. Điều này có thể xảy ra bất cứ lúc nào trong quá trình thực thi Ứng dụng thông thường, nhưng nó sẽ dừng ở một cuộc gọi hệ thống gốc, vì việc chuyển ngữ cảnh được thực hiện ở cấp hạt nhân. Vì vậy - đây là nơi mà Dalvik GC tham gia câu chuyện.

Mã Dal Dal (như được triển khai trong dự án Dalvik trong trang AOSP) không phải là một đoạn mã phức tạp. Cách thức cơ bản mà nó hoạt động được trình bày trong các slide DroidCon của tôi. Những gì tôi đã không bao gồm là vòng lặp GC cơ bản - tại điểm mà trình thu thập có một danh sách các Đối tượng cần hoàn thiện (và hủy). Logic vòng lặp ở cơ sở có thể được đơn giản hóa như thế này:

  1. lấy starting_timestamp ,
  2. xóa đối tượng cho danh sách các đối tượng để phát hành,
  3. phát hành đối tượng - finalize()và gọi bản địadestroy() nếu được yêu cầu,
  4. lấy end_timestamp ,
  5. tính toánend_timestamp - starting_timestamp ) và so sánh với giá trị thời gian chờ được mã hóa cứng là 10 giây,
  6. nếu hết thời gian - ném java.util.concurrent.TimeoutExceptionvà giết quá trình.

Bây giờ hãy xem xét kịch bản sau đây:

Ứng dụng chạy dọc làm việc của nó.

Đây không phải là một ứng dụng phải đối mặt với người dùng, nó chạy trong nền.

Trong hoạt động nền này, các đối tượng được tạo, sử dụng và cần được thu thập để giải phóng bộ nhớ.

Ứng dụng không bận tâm với WakeLock - vì điều này sẽ ảnh hưởng xấu đến pin và dường như không cần thiết.

Điều này có nghĩa là Ứng dụng sẽ thỉnh thoảng gọi cho GC.

Thông thường các lần chạy GC được hoàn thành mà không gặp trở ngại nào.

Đôi khi (rất hiếm khi) hệ thống sẽ quyết định ngủ ở giữa đường chạy của GC.

Điều này sẽ xảy ra nếu bạn chạy ứng dụng của mình đủ lâu và theo dõi nhật ký bộ nhớ Dalvik chặt chẽ.

Bây giờ - hãy xem xét logic dấu thời gian của vòng lặp GC cơ bản - thiết bị có thể bắt đầu chạy, thực hiện start_stampvà đi ngủ theo destroy()cuộc gọi riêng trên một đối tượng hệ thống.

Khi nó thức dậy và tiếp tục chạy, destroy()nó sẽ kết thúc và tiếp theo end_stampsẽ là thời gian nó diễn radestroy() cuộc gọi + thời gian ngủ.

Nếu thời gian ngủ dài (hơn 10 giây), java.util.concurrent.TimeoutExceptionsẽ bị ném.

Tôi đã thấy điều này trong các biểu đồ được tạo từ tập lệnh python phân tích - dành cho Ứng dụng Hệ thống Android, không chỉ các ứng dụng được theo dõi của riêng tôi.

Thu thập đủ nhật ký và cuối cùng bạn sẽ thấy nó.

Dòng dưới cùng:

Vấn đề không thể tránh được - bạn sẽ gặp phải nó nếu ứng dụng của bạn chạy trong nền.

Bạn có thể giảm thiểu bằng cách sử dụng WakeLock và ngăn thiết bị ngủ, nhưng đó là một câu chuyện hoàn toàn khác, và một cơn đau đầu mới, và có thể là một cuộc nói chuyện khác ở một kẻ lừa đảo khác.

Bạn có thể giảm thiểu vấn đề bằng cách giảm các cuộc gọi GC - làm cho kịch bản ít xảy ra hơn (các mẹo nằm trong các slide).

Tôi chưa có cơ hội xem qua mã GC Dalvik 2 (còn gọi là ART) - tự hào có tính năng Nén thế hệ mới hoặc thực hiện bất kỳ thử nghiệm nào trên Android Lollipop.

Đã thêm ngày 7/5/2015:

Sau khi xem xét tổng hợp báo cáo sự cố cho loại sự cố này, có vẻ như các sự cố này từ phiên bản 5.0 trở lên của HĐH Android (Lollipop với ART) chỉ chiếm 0,5% loại sự cố này. Điều này có nghĩa là những thay đổi của ART GC đã làm giảm tần suất của các sự cố này.

Đã thêm ngày 6/1/2016:

Có vẻ như dự án Android đã bổ sung rất nhiều thông tin về cách thức hoạt động của GC trong Dalvik 2.0 (hay còn gọi là ART).

Bạn có thể đọc về nó ở đây - Gỡ lỗi Bộ sưu tập Rác ART .

Nó cũng thảo luận về một số công cụ để có được thông tin về hành vi của GC cho ứng dụng của bạn.

Gửi SIGQUIT cho quy trình ứng dụng của bạn về cơ bản sẽ gây ra ANR và chuyển trạng thái ứng dụng vào tệp nhật ký để phân tích.


Trong trường hợp của tôi, tôi cũng dự định cố gắng giảm thiểu điều này bằng cách tìm cách giảm số lượng mã / thời gian tôi đang chạy trong nền. Cảm ơn nghiên cứu của bạn về chủ đề này.
parkerfath

loại bỏ bất kỳ xử lý nền được thực hiện trong ứng dụng của bạn sẽ giúp giảm đáng kể vấn đề.
oba

Đối với những gì nó có giá trị, điều này vẫn xảy ra trong Marshmallow (6.0.1). Điều đó nói rằng, tôi chỉ nhận được lỗi này một lần. Vì vậy, nó dường như không phải là một vấn đề lớn. Cảm ơn bạn đã giải thích kỹ lưỡng của bạn.
Knossos

Sau một thời gian, tôi có ấn tượng khác biệt rằng việc khắc phục sự cố này trong HĐH là rất có vấn đề và cần có sự hợp tác giữa Google và các OEM. Tôi không mong đợi điều này sẽ được khắc phục sớm.
oba

Tôi đang sử dụng wakelock nhưng vẫn gặp phải sự cố này trên Android 4.4.2. Ứng dụng của tôi có một số hoạt động nền nhưng chủ yếu được thiết kế để hoạt động cả ngày trong khi sạc cáp. Có cách nào khác để giảm thiểu vấn đề này không?
Orcun Sevsay

74

Chúng tôi thấy điều này liên tục, trên tất cả các ứng dụng của chúng tôi, sử dụng Crashlytics. Sự cố thường xảy ra trong mã nền tảng. Một mẫu nhỏ:

android.database.CoderWindow.finalize () đã hết thời gian sau 10 giây

java.util.regex.Matcher.finalize () đã hết thời gian sau 10 giây

android.graphics.Bitmap $ BitmapFinalizer.finalize () đã hết thời gian sau 10 giây

org.apache.http.impl.conn.SingleClientConnManager.finalize () đã hết thời gian sau 10 giây

java.util.concản.ThreadPoolExecutor.finalize () đã hết thời gian sau 10 giây

android.os.BinderProxy.finalize () đã hết thời gian sau 10 giây

android.graphics.Path.finalize () đã hết thời gian sau 10 giây

Các thiết bị mà điều này xảy ra là các thiết bị áp đảo (nhưng không độc quyền) do Samsung sản xuất. Điều đó chỉ có nghĩa là hầu hết người dùng của chúng tôi đang sử dụng các thiết bị của Samsung; cách khác, nó có thể chỉ ra một vấn đề với các thiết bị Samsung. Tôi không thực sự chắc chắn.

Tôi cho rằng điều này không thực sự trả lời câu hỏi của bạn, nhưng tôi chỉ muốn củng cố rằng điều này có vẻ khá phổ biến và không cụ thể cho ứng dụng của bạn.


16
Nó cũng xảy ra với phiên bản Android 5.0.1 và dường như không bị hạn chế đối với các thiết bị Samsung. Nó đã xảy ra trên Nexus 6.
Shobhit Puri

4
Tôi gặp sự cố này trên Android 4.4.4 với thiết bị được sản xuất bởi XIAOMI
Paresh Dudhat

Chỉ muốn kêu lên rằng chúng ta đang thấy phần lớn các sự cố này trên máy tính bảng samsung. Không chắc Samsung đã làm gì khác với cách máy tính bảng xử lý các ứng dụng chạy nền.
FriendlyMikhail

1
tôi có vấn đề này trên Android 4.4.4. thiết bị được sản xuất bởi HUAWEI.
Rameshbabu

1
Ứng dụng của tôi gặp sự cố sau khi tôi sử dụng thư viện canary rò rỉ trên thiết bị Android 5.0.2 Samsung. Nếu tôi tắt khởi tạo thư viện, ứng dụng sẽ hoạt động tốt.
vanomart

15

Tôi tìm thấy một số slide về vấn đề này.

http://de.sl slideshoware.net/DroidConTLV/android-crash-analysis-and-the-dalvik-garbage-collector-tools-and-tips

Trong các slide này, tác giả nói rằng nó dường như là một vấn đề với GC, nếu có rất nhiều đối tượng hoặc các đối tượng khổng lồ trong đống. Bản trình chiếu cũng bao gồm một tham chiếu đến một ứng dụng mẫu và tập lệnh python để phân tích vấn đề này.

https://github.com/oba2cat3/GCTest

https://github.com/oba2cat3/logcat2memorygraph

Hơn nữa, tôi đã tìm thấy một gợi ý trong nhận xét số 3 ở bên này: https://code.google.com.vn/p/android/issues/detail?id=53418#c3


7

Chúng tôi đã giải quyết vấn đề bằng cách dừng lại FinalizerWatchdogDaemon.

public static void fix() {
    try {
        Class clazz = Class.forName("java.lang.Daemons$FinalizerWatchdogDaemon");

        Method method = clazz.getSuperclass().getDeclaredMethod("stop");
        method.setAccessible(true);

        Field field = clazz.getDeclaredField("INSTANCE");
        field.setAccessible(true);

        method.invoke(field.get(null));

    }
    catch (Throwable e) {
        e.printStackTrace();
    }
}

Bạn có thể gọi phương thức trong vòng đời của Ứng dụng, như thế nào attachBaseContext(). Vì lý do tương tự, bạn cũng có thể chỉ định việc sản xuất điện thoại để khắc phục sự cố, tùy bạn.


Không làm việc cho chúng tôi, tôi không thể hiểu tại sao. Mã hoàn thành không có ngoại lệ nhưng chúng tôi vẫn nhận được các sự cố đó trong báo cáo Crashlytics và Google Play Console.
Anton Breusov

5

Phát sóng nhận thời gian chờ sau 10 giây. Có thể bạn đang thực hiện một cuộc gọi không đồng bộ (sai) từ máy thu quảng bá và 4.3 thực sự phát hiện ra nó.


3
Có vẻ vô dụng để phát hiện ra nó và không cho bạn biết đủ về nó. Cho chúng tôi biết chương trình phát sóng nào sẽ tốt đẹp.
Aaron T Harris

Xin lỗi nếu tôi sai, nhưng tôi không nghĩ rằng thời gian chờ máy thu phát sóng gây ra sự cố cụ thể này. Đó là một thực hành tốt để tránh giới hạn 10 giây, nhưng đó là một vấn đề khác với người yêu cầu đang gặp phải.
parkerfath

Tôi chỉ có 10 giây trên não. developer.android.com/training/articles/perf-anr.html IDK nếu nó gây ra sự cố.
danny117

Quan điểm của bạn là vững chắc và một thực hành tốt. Tuy nhiên, người đăng ban đầu có một câu hỏi cụ thể về một bộ thiết bị cụ thể. Tôi khuyên người xem khác của bài đăng này kiểm tra câu trả lời của Christopher và câu trả lời của oba nếu họ thấy các triệu chứng tương tự (thiết bị Samsung (đặc biệt là Galaxy S 4), v.v.)
parkerfath

Tôi không ở đây để bash thiết bị sản xuất nó sẽ trái với các điều khoản.
danny117 13/03/2015

5

Đây là một giải pháp hiệu quả từ didi để giải quyết vấn đề này, vì lỗi này rất phổ biến và khó tìm ra nguyên nhân, Nó trông giống như một vấn đề hệ thống, Tại sao chúng ta không thể bỏ qua trực tiếp Tất nhiên chúng ta có thể bỏ qua nó, Tại đây là mã mẫu:

final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = 
        Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        if (t.getName().equals("FinalizerWatchdogDaemon") && e instanceof TimeoutException) {
        } else {
            defaultUncaughtExceptionHandler.uncaughtException(t, e);
        }
    }
});

Bằng cách đặt trình xử lý ngoại lệ chưa được mặc định đặc biệt, ứng dụng có thể thay đổi cách xử lý các ngoại lệ chưa được xử lý cho các luồng đã chấp nhận bất kỳ hành vi mặc định nào mà hệ thống cung cấp. Khi một TimeoutExceptionđứa trẻ bị ném ra từ một chủ đề có tênFinalizerWatchdogDaemon , trình xử lý đặc biệt này sẽ chặn chuỗi trình xử lý, trình xử lý hệ thống sẽ không được gọi, do đó sẽ tránh được sự cố.

Thông qua thực hành, không có tác động xấu khác được tìm thấy. Hệ thống GC vẫn hoạt động, thời gian chờ được giảm bớt khi mức sử dụng CPU giảm.

Để biết thêm chi tiết, hãy xem: https://mp.weixin.qq.com/s/uFcFYO2GtWWiblotem2bGg


4

Một điều luôn luôn đúng là vào thời điểm này, thiết bị sẽ bị nghẹt thở đối với một số bộ nhớ (thường là lý do khiến GC rất có thể bị kích hoạt).

Như hầu hết các tác giả đã đề cập trước đó, vấn đề này xuất hiện khi Android cố gắng chạy GC trong khi ứng dụng ở chế độ nền. Trong hầu hết các trường hợp chúng tôi quan sát thấy nó, người dùng đã tạm dừng ứng dụng bằng cách khóa màn hình của họ. Điều này cũng có thể cho thấy rò rỉ bộ nhớ ở đâu đó trong ứng dụng hoặc thiết bị đã quá tải. Vì vậy, cách hợp pháp duy nhất để giảm thiểu nó là:

  • để đảm bảo không có rò rỉ bộ nhớ và
  • để giảm dung lượng bộ nhớ của ứng dụng nói chung.

1
try {
    Class<?> c = Class.forName("java.lang.Daemons");
    Field maxField = c.getDeclaredField("MAX_FINALIZE_NANOS");
    maxField.setAccessible(true);
    maxField.set(null, Long.MAX_VALUE);
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (NoSuchFieldException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}

Điều này sẽ không giải quyết được vấn đề trong trường hợp thời lượng Ngủ là> 100 giây. Tại sao không đặt nó thành MAX_INT?
oba

Vâng, tôi chỉ làm ví dụ ~
kot32

1
Điều này không nên làm việc vì liên tục nội tuyến. Thay đổi giá trị trường sẽ không ảnh hưởng đến giá trị được gọi cho người gọi.
hqzxzwb

0

FinalueQueue có thể quá dài

Tôi nghĩ rằng java có thể yêu cầu GC.SuppressFinalize () & GC.ReRegisterForFinalize () để cho phép người dùng giảm độ dài một cách rõ ràng

nếu mã nguồn của JVM có sẵn, chúng ta có thể tự thực hiện các phương thức này, chẳng hạn như trình tạo ROM Android


0

Có vẻ như lỗi Android Runtime. Dường như có bộ hoàn thiện chạy trong luồng riêng biệt của nó và gọi phương thức Finalize () trên các đối tượng nếu chúng không nằm trong khung hiện tại của stacktrace. Ví dụ mã sau (được tạo để xác minh sự cố này) đã kết thúc với sự cố.

Chúng ta hãy có một số con trỏ thực hiện một cái gì đó trong phương thức hoàn thiện (ví dụ: SqlCodes, đóng close () để khóa cơ sở dữ liệu hiện đang sử dụng)

private static class MyCur extends MatrixCursor {


    public MyCur(String[] columnNames) {
        super(columnNames);
    }

    @Override
    protected void finalize() {
        super.finalize();

        try {
            for (int i = 0; i < 1000; i++)
                Thread.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Và chúng tôi làm một số công cụ chạy dài đã mở con trỏ:

for (int i = 0; i < 7; i++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                MyCur cur = null;
                try {
                    cur = new MyCur(new String[]{});
                    longRun();
                } finally {
                    cur.close();
                }
            }

            private void longRun() {
                try {
                    for (int i = 0; i < 1000; i++)
                        Thread.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

Điều này gây ra lỗi sau:

FATAL EXCEPTION: FinalizerWatchdogDaemon
                                                                        Process: la.la.land, PID: 29206
                                                                        java.util.concurrent.TimeoutException: MyCur.finalize() timed out after 10 seconds
                                                                            at java.lang.Thread.sleep(Native Method)
                                                                            at java.lang.Thread.sleep(Thread.java:371)
                                                                            at java.lang.Thread.sleep(Thread.java:313)
                                                                            at MyCur.finalize(MessageList.java:1791)
                                                                            at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:222)
                                                                            at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:209)
                                                                            at java.lang.Thread.run(Thread.java:762)

Biến thể sản xuất với SqlCodes rất giống nhau:

12-21 15:40:31.668: E/EH(32131): android.content.ContentResolver$CursorWrapperInner.finalize() timed out after 10 seconds
12-21 15:40:31.668: E/EH(32131): java.util.concurrent.TimeoutException: android.content.ContentResolver$CursorWrapperInner.finalize() timed out after 10 seconds
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Object.wait(Native Method)
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Thread.parkFor$(Thread.java:2128)
12-21 15:40:31.668: E/EH(32131): 	at sun.misc.Unsafe.park(Unsafe.java:325)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:840)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:873)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:200)
12-21 15:40:31.668: E/EH(32131): 	at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
12-21 15:40:31.668: E/EH(32131): 	at net.sqlcipher.database.SQLiteDatabase.lock(SourceFile:518)
12-21 15:40:31.668: E/EH(32131): 	at net.sqlcipher.database.SQLiteProgram.close(SourceFile:294)
12-21 15:40:31.668: E/EH(32131): 	at net.sqlcipher.database.SQLiteQuery.close(SourceFile:136)
12-21 15:40:31.668: E/EH(32131): 	at net.sqlcipher.database.SQLiteCursor.close(SourceFile:510)
12-21 15:40:31.668: E/EH(32131): 	at android.database.CursorWrapper.close(CursorWrapper.java:50)
12-21 15:40:31.668: E/EH(32131): 	at android.database.CursorWrapper.close(CursorWrapper.java:50)
12-21 15:40:31.668: E/EH(32131): 	at android.content.ContentResolver$CursorWrapperInner.close(ContentResolver.java:2746)
12-21 15:40:31.668: E/EH(32131): 	at android.content.ContentResolver$CursorWrapperInner.finalize(ContentResolver.java:2757)
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:222)
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:209)
12-21 15:40:31.668: E/EH(32131): 	at java.lang.Thread.run(Thread.java:762)

Tiếp tục: Đóng con trỏ càng sớm càng tốt. Ít nhất là trên Samsung S8 với Android 7, nơi vấn đề đã được nhìn thấy.


0

Đối với các lớp mà bạn tạo (tức là không phải là một phần của Android), có thể tránh sự cố hoàn toàn.

Bất kỳ lớp nào thực hiện finalize()đều có một số xác suất không thể tránh khỏi sự cố như được giải thích bởi @oba. Vì vậy, thay vì sử dụng các công cụ hoàn thiện để thực hiện dọn dẹp, hãy sử dụng a PhantomReferenceQueue.

Để biết ví dụ, hãy kiểm tra việc triển khai trong React Native: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/jni/DestructorThread.java

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.