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)
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.
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()

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

Nevertheless, String.format has overloading without passing Locale

that sets just to default Locale for Formatter.

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

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

FormattedFloatingDecimal is part of the sun.misc package that is not _Android-Changed_.

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

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.
Hi,
Our users are having the same problem on Android 8.1.0, but not on Fresco.
These are the devices:

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)
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.
yet another device
vivo(vivo Y85A) on android 8.1
Most helpful comment
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()However, there are _three_ concerns.
First of all, in the particular example
FLog.v()works with the conversion from primitives toString, not vice-versa. So, probably, there is no need to worry aboutLocaleproblems like,(comma) or.(dot) for decimals.Second, despite the fact of the
@NonNullargument,String.format()allows passing nullLocaleNevertheless,
String.formathas overloading without passingLocalethat sets just to default
LocaleforFormatter.I believe, the reason behind setting it to the
nullin theFLog.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
NPEhappens 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[] vwhich is not guardedBack to the caller,
print()shows that this is a mantissa which converts fromdoublevalue tochar[]with help ofFormattedFloatingDecimalFormattedFloatingDecimalis part of thesun.miscpackage that is not _Android-Changed_.And it's possible to obtain a
nullmantissa since it's not guarded.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
WebRTCteam that is part of the _Android SDK_ has faced the same problem 2 years ago where they specified it asand suggests a _Speculative_ fix by using
DecimalFormatinstead ofString.Formatfor floats.By the way, initially, they've had used
Locale.USinString.Formatwhile getting the problem, so it's feasible to assume the problem is not related to theLocale.On the other hand,
DecimalFormatdoesn't use anything fromsun.miscpackages.Conclusion.
I'm curious if the problem anyhow correlated with the fact that it's about
FormattedFloatingDecimalfromsun.miscpackage. Maybe these devices have been using some sort of customized _AOSP_? I've found no other evidence of the problem than that withWebRTC._Speculative_ fix is to use
DecimalFormat. The problem is that it has to be done throughFLog.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.