概述
基于此背景,开始兵分两路:
- 第一时间找到 A/B Testing SDK 的项目经理,请他来帮助协调版本发布的相关人员;
- 与此同时,我开始进行问题的定位分析。
三、独立分析
17 点 52 分
飞奔到家里,打开了客户提供的 crash 堆栈。该堆栈是客户从自己的分析平台里提取出来的,本地无法复现,堆栈如下:
main(1)
java.util.UnknownFormatConversionException
Conversion = ‘_’
还原失败(未找到符号表)(404_1_0_2_0_0_0_0_9_0)
解析原始
1 java.util.Formatter
F
o
r
m
a
t
S
p
e
c
i
f
i
e
r
.
c
o
n
v
e
r
s
i
o
n
(
F
o
r
m
a
t
t
e
r
.
j
a
v
a
:
2782
)
2
j
a
v
a
.
u
t
i
l
.
F
o
r
m
a
t
t
e
r
FormatSpecifier.conversion(Formatter.java:2782) 2 java.util.Formatter
FormatSpecifier.conversion(Formatter.java:2782)2java.util.FormatterFormatSpecifier.(Formatter.java:2812)
3 java.util.Formatter$FormatSpecifierParser.(Formatter.java:2625)
4 java.util.Formatter.parse(Formatter.java:2558)
5 java.util.Formatter.format(Formatter.java:2505)
6 java.util.Formatter.format(Formatter.java:2459)
7 java.lang.String.format(String.java:2870)
8 com.sensorsdata.abtest.a.c.a(SABErrorDispatcher.java:29)
9 com.sensorsdata.abtest.a.d$3.a(SensorsABTestApiRequestHelper.java:236)
10 com.sensorsdata.abtest.a.d$2.onFailure(SensorsABTestApiRequestHelper.java:185)
11 com.sensorsdata.analytics.android.sdk.network.HttpCallback
1.
r
u
n
(
H
t
t
p
C
a
l
l
b
a
c
k
.
j
a
v
a
:
46
)
12
a
n
d
r
o
i
d
.
o
s
.
H
a
n
d
l
e
r
.
h
a
n
d
l
e
C
a
l
l
b
a
c
k
(
H
a
n
d
l
e
r
.
j
a
v
a
:
900
)
13
a
n
d
r
o
i
d
.
o
s
.
H
a
n
d
l
e
r
.
d
i
s
p
a
t
c
h
M
e
s
s
a
g
e
(
H
a
n
d
l
e
r
.
j
a
v
a
:
103
)
14
a
n
d
r
o
i
d
.
o
s
.
L
o
o
p
e
r
.
l
o
o
p
(
L
o
o
p
e
r
.
j
a
v
a
:
219
)
15
a
n
d
r
o
i
d
.
a
p
p
.
A
c
t
i
v
i
t
y
T
h
r
e
a
d
.
m
a
i
n
(
A
c
t
i
v
i
t
y
T
h
r
e
a
d
.
j
a
v
a
:
8387
)
16
j
a
v
a
.
l
a
n
g
.
r
e
f
l
e
c
t
.
M
e
t
h
o
d
.
i
n
v
o
k
e
(
N
a
t
i
v
e
M
e
t
h
o
d
)
17
c
o
m
.
a
n
d
r
o
i
d
.
i
n
t
e
r
n
a
l
.
o
s
.
R
u
n
t
i
m
e
I
n
i
t
1.run(HttpCallback.java:46) 12 android.os.Handler.handleCallback(Handler.java:900) 13 android.os.Handler.dispatchMessage(Handler.java:103) 14 android.os.Looper.loop(Looper.java:219) 15 android.app.ActivityThread.main(ActivityThread.java:8387) 16 java.lang.reflect.Method.invoke(Native Method) 17 com.android.internal.os.RuntimeInit
1.run(HttpCallback.java:46)12android.os.Handler.handleCallback(Handler.java:900)13android.os.Handler.dispatchMessage(Handler.java:103)14android.os.Looper.loop(Looper.java:219)15android.app.ActivityThread.main(ActivityThread.java:8387)16java.lang.reflect.Method.invoke(NativeMethod)17com.android.internal.os.RuntimeInitMethodAndArgsCaller.run(RuntimeInit.java:513)
18 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
结合上下文分析发现:接口请求失败时,SDK 会打印错误日志。在打印的过程中调用 format 方法导致 UnknownFormatConversionException 异常。
通过上述分析,问题排查范围缩小到:调用 format 方法导致的 crash,并将初步排查结论同步给客户和客户成功。
正在进一步定位为什么会导致 crash 时,突然发现我已经被拉进「紧急处理 Android A/B Testing SDK 崩溃问题」企业微信群。
四、抽丝剥茧
18 点 04 分
进入到专项问题讨论群后,技术顾问向客户确认了更多的信息,例如 crash 的机型、次数、版本等,进一步完善了问题的周边信息。
此时,群内各位大佬纷纷出谋划策,尝试复现 crash。
思路一:format 方法的第一个参数存在特殊字符 '% ’
String.format(“where name like % %s”,“Zhang san”);
format 方法传入特殊字符,尝试复现,crash 堆栈如下:
Exception in thread “main” java.util.IllegalFormatFlagsException: Flags = ’ ’
at java.util.Formatter
F
o
r
m
a
t
S
p
e
c
i
f
i
e
r
.
c
h
e
c
k
T
e
x
t
(
F
o
r
m
a
t
t
e
r
.
j
a
v
a
:
3037
)
a
t
j
a
v
a
.
u
t
i
l
.
F
o
r
m
a
t
t
e
r
FormatSpecifier.checkText(Formatter.java:3037) at java.util.Formatter
FormatSpecifier.checkText(Formatter.java:3037)atjava.util.FormatterFormatSpecifier.(Formatter.java:2733)
at java.util.Formatter.parse(Formatter.java:2560)
at java.util.Formatter.format(Formatter.java:2501)
at java.util.Formatter.format(Formatter.java:2455)
at java.lang.String.format(String.java:2940)
at com.zxwei.cf.lib.MyClass.main(MyClass.java:22)
可见,这个堆栈和实际的 crash 堆栈不一致。
思路二:format 方法的第一个参数为 null
String.format(null,“Zhang san”);
format 方法传入 null,此时 crash 堆栈如下:
Exception in thread “main” java.lang.NullPointerException
at java.util.regex.Matcher.getTextLength(Matcher.java:1283)
at java.util.regex.Matcher.reset(Matcher.java:309)
at java.util.regex.Matcher.(Matcher.java:229)
at java.util.regex.Pattern.matcher(Pattern.java:1093)
at java.util.Formatter.parse(Formatter.java:2547)
at java.util.Formatter.format(Formatter.java:2501)
at java.util.Formatter.format(Formatter.java:2455)
at java.lang.String.format(String.java:2940)
at com.zxwei.cf.lib.MyClass.main(MyClass.java:24)
比对堆栈信息,发现和实际的 crash 堆栈还是不一致。
思路三:format 方法的第一个参数存在特殊字符 ‘%_’
String.format(“where name like %_”,“Zhang san”);
通过这种方式的模拟,堆栈如下:
Exception in thread “main” java.util.UnknownFormatConversionException: Conversion = ‘_’
at java.util.Formatter.checkText(Formatter.java:2579)
at java.util.Formatter.parse(Formatter.java:2565)
at java.util.Formatter.format(Formatter.java:2501)
at java.util.Formatter.format(Formatter.java:2455)
at java.lang.String.format(String.java:2940)
at com.zxwei.cf.lib.MyClass.main(MyClass.java:22)
和实际的 crash 堆栈是一样的,但实际项目中 format 方法的第一个参数是不变的,不可能会出现特殊字符。
at com.zxwei.cf.lib.MyClass.main(MyClass.java:22)
和实际的 crash 堆栈是一样的,但实际项目中 format 方法的第一个参数是不变的,不可能会出现特殊字符。
最后
以上就是健壮小猫咪为你收集整理的一群人的战斗,实战篇三、独立分析四、抽丝剥茧的全部内容,希望文章能够帮你解决一群人的战斗,实战篇三、独立分析四、抽丝剥茧所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复