facebook / fresco

An Android library for managing images and the memory they use.
https://frescolib.org/
MIT License
17.05k stars 3.75k forks source link

Fatal Exception: java.lang.NullPointerException: Attempt to get length of null array #2504

Open Discovery-Prachi opened 4 years ago

Discovery-Prachi commented 4 years ago

We are getting following crash on Crashlytics for good number of users with Android OS 8, with more than 47 devices. We are using "com.facebook.fresco:fresco:2.2.0"

Could you please help us, since its happening on. multiple users.

Logs :

Fatal Exception: java.lang.NullPointerException: Attempt to get length of null array at java.util.Formatter$FormatSpecifier.addZeros(Formatter.java:3505) at java.util.Formatter$FormatSpecifier.print(Formatter.java:3401) at java.util.Formatter$FormatSpecifier.print(Formatter.java:3332) at java.util.Formatter$FormatSpecifier.print(Formatter.java:3317) at java.util.Formatter$FormatSpecifier.printFloat(Formatter.java:2891) at java.util.Formatter$FormatSpecifier.print(Formatter.java:2844) at java.util.Formatter.format(Formatter.java:2523) at java.util.Formatter.format(Formatter.java:2458) at java.lang.String.format(String.java:2814) at com.facebook.common.logging.FLog.formatString(FLog.java:491) at com.facebook.common.logging.FLog.v(FLog.java:118) at com.facebook.imagepipeline.transcoder.DownsampleUtil.determineDownsampleRatio(DownsampleUtil.java:87) at com.facebook.imagepipeline.transcoder.DownsampleUtil.determineSampleSize(DownsampleUtil.java:43) at com.facebook.imagepipeline.producers.DecodeProducer$ProgressiveDecoder$1.run(DecodeProducer.java:163) at com.facebook.imagepipeline.producers.JobScheduler.doJob(JobScheduler.java:202) at com.facebook.imagepipeline.producers.JobScheduler.access$000(JobScheduler.java:22) at com.facebook.imagepipeline.producers.JobScheduler$1.run(JobScheduler.java:73) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) at com.facebook.imagepipeline.core.PriorityThreadFactory$1.run(PriorityThreadFactory.java:51) at java.lang.Thread.run(Thread.java:764)

oprisnik commented 4 years ago

Thanks for the bug report.

That's weird, looks like the log statement is failing: https://github.com/facebook/fresco/blob/e791687a6617eaeb5f8e5524452541777ddc4aa4/imagepipeline-base/src/main/java/com/facebook/imagepipeline/transcoder/DownsampleUtil.java#L103

Setting your log level to anything that's smaller than verbose (like ERROR or WARN) should help: FLog.setMinimumLoggingLevel(WARN)

Ideally, we should figure out why String.format is failing here.

tsybanov commented 4 years ago

I was curious about the problem the other day, even without the evidence and ability to reproduce it. Here is what I've found.

Initially, I was thinking that the problem somehow related to the locale that has not been set up in FLog.formatString()

Screen Shot 2020-07-13 at 2 20 27 PM

However, there are three concerns. First of all, in the particular example FLog.v() works with the conversion from primitives to String, not vice-versa. So, probably, there is no need to worry about Locale problems like , (comma) or . (dot) for decimals.

Second, despite the fact of the @NonNull argument, String.format() allows passing null Locale

Screen Shot 2020-07-13 at 2 26 11 PM

Nevertheless, String.format has overloading without passing Locale

Screen Shot 2020-07-13 at 2 34 13 PM

that sets just to default Locale for Formatter.

Screen Shot 2020-07-13 at 2 35 22 PM

I believe, the reason behind setting it to the null in the FLog.formatString() is that Lint has a LocaleDetector check that reminds about that decision. So, probably, that was a way to suppress it? If it is then, I believe, it's not a good practice.

And the last concern is the reason why NPE happens in the first place. If to look down the road of the stack, the problem is in Formatter.addZeroes() where it's simply one of the arguments, char[] v which is not guarded

Screen Shot 2020-07-13 at 3 04 37 PM

Back to the caller, print() shows that this is a mantissa which converts from double value to char[] with help of FormattedFloatingDecimal

Screen Shot 2020-07-13 at 3 09 39 PM

FormattedFloatingDecimal is part of the sun.misc package that is not Android-Changed.

Screen Shot 2020-07-13 at 3 11 13 PM

And it's possible to obtain a null mantissa since it's not guarded.

Screen Shot 2020-07-13 at 3 14 15 PM

However, in all cases of the constructor logic mantissa has to be assigned, even if it's just new char[0].

At the same time, I've found that WebRTC team that is part of the Android SDK has faced the same problem 2 years ago where they specified it as

crashes... on some devices

and suggests a Speculative fix by using DecimalFormat instead of String.Format for floats. By the way, initially, they've had used Locale.US in String.Format while getting the problem, so it's feasible to assume the problem is not related to the Locale.

On the other hand, DecimalFormat doesn't use anything from sun.misc packages.

Conclusion.

I'm curious if the problem anyhow correlated with the fact that it's about FormattedFloatingDecimal from sun.misc package. Maybe these devices have been using some sort of customized AOSP? I've found no other evidence of the problem than that with WebRTC.

Speculative fix is to use DecimalFormat. The problem is that it has to be done through FLog.formatString() since the problem is in there.

@pnkshir it would be great to have a bit more information about the devices with crashes if it's possible. @oprisnik Please, let me know what you think and if there are enough reasons to apply a Speculative fix.

janbolat commented 3 years ago

Hi, Our users are having the same problem on Android 8.1.0, but not on Fresco. These are the devices: image Xiaomi Redmi 6 Pro Xiaomi Redmi 5 Plus Vivo V1818A Vivo V1732A Samsung Galaxy J7(2016) Samsung Galaxy J2 Core OPPO A5 Huawei Y3 2018

It is failing on formatting the latitude and longitude (double): String.format(Locale.ENGLISH, "%.6f", latitude)

oprisnik commented 3 years ago

Hey @tsybanov - thank you for the detailed report and sorry for the late reply.

I think we should try your speculative fix, so it would be great if you could submit a PR.

wuqian commented 3 years ago

yet another device

vivo(vivo Y85A) on android 8.1

kritipchakrabarti commented 2 years ago

@oprisnik

Can you please explain the issue(#2504) a little bit to understand the issue well. I would like to contribute to this issue.

AndroidKolla commented 2 years ago

Hi All Friend I Need Your Help to Fix This java.lang.RuntimeException: at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3654) at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3812) at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:83) at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2267) at android.os.Handler.dispatchMessage (Handler.java:107) at android.os.Looper.loop (Looper.java:237) at android.app.ActivityThread.main (ActivityThread.java:8161) at java.lang.reflect.Method.invoke (Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:496) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1100) Caused by: java.lang.NullPointerException: at com.deepthistudio.sinhalabehethapp.Logo_Screen.onCreate (Logo_Screen.java:19) at android.app.Activity.performCreate (Activity.java:7963) at android.app.Activity.performCreate (Activity.java:7952) at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1307) at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3629)

nitesh-github143 commented 1 year ago

I am a newbie and willing to contribute to this project. Can I get started with this please.

nitesh-github143 commented 1 year ago

I am a newbie and willing to contribute to this project. Can I get started with this please.

harsh-1806 commented 1 year ago

Can someone help me with understanding the codebase I am a newbie just starting to contribute. Please

jacklyq commented 11 months ago

I am curious to hear if the speculative fix has worked?

tsybanov commented 11 months ago

@jacklyq The PR: https://github.com/facebook/fresco/pull/2552 was never approved

amrouchk commented 6 months ago

On your onStart method, you are using the Connectivity.isConnected method without checking if it returns true. If the device is not connected, it will proceed to show a Toast message but still attempt to execute the code inside the postDelayed handler, which might lead to issues.

Here's an updated version of the onStart method with proper null checks and restructured logic:

@Override
protected void onStart() {
    super.onStart();
    Context context = getApplicationContext();

    if (Connectivity.isConnected(context)) {
        final MySharedPreferences mySharedPreferences = new MySharedPreferences(this);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (mySharedPreferences != null && mySharedPreferences.getBooleanVal(key_first_install)) {
                    Intent intent = new Intent(Logo_screen.this, dang_nhap.class);
                    startActivity(intent);
                    overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left);
                    finish();
                } else {
                    Intent intent = new Intent(Logo_screen.this, waiting.class);
                    if (mySharedPreferences != null) {
                        mySharedPreferences.putBooleanVal(key_first_install, true);
                    }
                    startActivity(intent);
                    overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left);
                    finish();
                }
            }
        }, SPLASH_SCREEN);
    } else {
        Toast.makeText(context, "show a toast msg ", Toast.LENGTH_SHORT).show();
    }
}

This modification includes null checks for mySharedPreferences before using it. Additionally, the Connectivity.isConnected check is used to decide whether to proceed with the delayed task or simply show a toast message if there is no network connectivity.

amrouchk commented 6 months ago

This is from the class Logo_Screen.java

SharanyaR07 commented 1 week ago

Hey, Is anyone ready to help me out understand the issue more clearly? I've just started contributing and am curious to learn more.