網易即時通訊的沙雕操作
背景
很久以前的事了。造成了崩潰率上升。
APP發現有很多oom,於是做個優化吧,優化裏有這麼一個操作,低內存的時候清除一下內存中圖片glide的緩存。
發生問題
於是在application裏的onLowMemory方法裏:
(我記得是這個方法,已經很久遠了,可能記得不太清,總之是調的glide的方法)
Glide.get(instance).clearMemory();
可惜萬萬沒想到,APP內集成了網易即時通訊的uikit這個demo,連改都沒有改。
這個demo裏也引用了Glide圖片緩存庫,有這麼一個類:NIMGlideModule
他做了這麼個操作:
private static final String TAG = "NIMGlideModule";
private static final int M = 1024 * 1024;
private static final int MAX_DISK_CACHE_SIZE = 256 * M;
/**
* ************************ Memory Cache ************************
*/
static void clearMemoryCache(Context context) {
Glide.get(context).clearMemory();
}
/**
* ************************ GlideModule override ************************
*/
@Override
public void applyOptions(Context context, GlideBuilder builder) {
// sdcard/Android/data/com.netease.nim.demo/glide
final String cachedDirName = "glide";
builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, cachedDirName, MAX_DISK_CACHE_SIZE));
LogUtil.i(TAG, "NIMGlideModule apply options, disk cached path=" + context.getExternalCacheDir() + File.pathSeparator + cachedDirName);
}
@Override
public void registerComponents(Context context, Glide glide) {
}
}
乍一看,沒什麼問題是吧。但是APP上線之後問題就出在這裏了。
爲什麼呢,先記住這裏的LogUtil,打印日誌的tag是static的。可能說到這裏,有些人就知道怎麼回事了。我們看一下網易的LogUtil:
public static void d(String tag, String msg) {
log.d(buildTag(tag), buildMessage(msg));
}
protected static String buildTag(String tag) {
return TextUtils.isEmpty(process) ? tag : "[" + process + "]" + tag;
}
logutil後面還有很多內容就不需要看了,他從來沒有對tag進行非空判斷。
看吧,低內存的時候,Android系統會幹什麼?
沒錯,優先清除static變量,呵呵?。
於是低內存的時候,我在清理Glide中內存的緩存,而網易即時通訊的uikit,卻在配置Glide的地方,打印了一個static修飾的tag的日誌,並且這個tag被回收,變爲null。
於是造成了空指針崩潰。
我尼瑪騷操作。tag能用static的還不判空。
解決
崩潰率上升了,怎麼辦?發版本修復啊,沒有熱更新我能怎麼辦,我也很崩潰啊。
扯扯犢子
騷。真的騷。