成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

安卓TV插件化9.0內(nèi)聯(lián)崩潰原因及解決方案

移動(dòng)開發(fā)
本文從內(nèi)聯(lián)崩潰的背景開始介紹,再結(jié)合 TV 端的插件化特點(diǎn)深入分析產(chǎn)生的原因,最后給出 TV 端的解決方案。
?安卓 TV 端應(yīng)用的更新比較困難,一方面是受限于各個(gè)設(shè)備廠商的規(guī)則,應(yīng)用更新策略比較慢,另一方面是 TV 用戶主動(dòng)更新的意愿比較低。因此插件化熱更新在安卓 TV 端就成為了有效更新應(yīng)用業(yè)務(wù)能力的必要技術(shù)手段,使用插件化熱更新技術(shù)能在不安裝新版 apk 的前提下,自動(dòng)地更新整個(gè)應(yīng)用的業(yè)務(wù)能力,不受系統(tǒng)本身的限制,不需要用戶選擇,極大地提升新版本的覆蓋率。

插件化技術(shù)本質(zhì)上是深度挖掘安卓系統(tǒng)的私有能力,需要對(duì)各個(gè)版本的安卓系統(tǒng)進(jìn)行適配。不但要保證低版本的低性能設(shè)備運(yùn)行順暢,也要保證高版本的系統(tǒng)是可以使用插件化升級(jí)的。隨著 TV 端高版本系統(tǒng)的比例逐漸增大,對(duì)高版本系統(tǒng)的適配成為了插件化技術(shù)的主要挑戰(zhàn)。為支持低性能設(shè)備的首次安裝運(yùn)行順暢,我們的插件化框架將插件加載功能與 TV 業(yè)務(wù)邏輯放在了同一個(gè) dex 中,但這樣的架構(gòu)在高版本系統(tǒng)上又會(huì)產(chǎn)生內(nèi)聯(lián)崩潰的問題,在既要保證低端設(shè)備性能的同時(shí),又要覆蓋到高版本設(shè)備的前提下,內(nèi)聯(lián)崩潰是一個(gè)無法簡(jiǎn)單繞過的一個(gè)問題。

本文從內(nèi)聯(lián)崩潰的背景開始介紹,再結(jié)合 TV 端的插件化特點(diǎn)深入分析產(chǎn)生的原因,最后給出 TV 端的解決方案。

01背景

什么是內(nèi)聯(lián)  

內(nèi)聯(lián)(inline)是一種編譯優(yōu)化方法。編譯器自動(dòng)地將函數(shù)體的代碼插入到這個(gè)函數(shù)的調(diào)用處,將函數(shù)調(diào)用展開為函數(shù)體的代碼。這種優(yōu)化能消除函數(shù)調(diào)用的開銷,但會(huì)使指令數(shù)量膨脹。

下面用 Kotlin 語言中的內(nèi)聯(lián)舉例:

圖片

Kotlin 的內(nèi)聯(lián)使用 inline 關(guān)鍵字定義內(nèi)聯(lián),將內(nèi)聯(lián)的選擇權(quán)完全交給了使用者,只要寫了 inline 關(guān)鍵字就一定會(huì)內(nèi)聯(lián)。另外,Kotlin 的內(nèi)聯(lián)觸發(fā)時(shí)機(jī)是編譯,在 Kotlin 編譯為字節(jié)碼的時(shí)候就會(huì)將 inline 函數(shù)調(diào)用展開,生成的字節(jié)碼不會(huì)調(diào)用內(nèi)聯(lián)方法,而是直接將指令插入到調(diào)用處。

Kotlin 語言的內(nèi)聯(lián)可以說是最簡(jiǎn)單的一種內(nèi)聯(lián),而本文要分析的內(nèi)聯(lián)崩潰的內(nèi)聯(lián)是 ART 虛擬機(jī)在將字節(jié)碼編譯為機(jī)器指令時(shí)進(jìn)行的內(nèi)聯(lián)。這種內(nèi)聯(lián)是完全自動(dòng)的,由 ART 虛擬機(jī)自己決定,沒有語言層面的機(jī)制去觸發(fā)它,而且根據(jù)不同版本的 ART 虛擬機(jī),內(nèi)聯(lián)的規(guī)則和細(xì)節(jié)都可能不同。它的觸發(fā)時(shí)機(jī)是運(yùn)行時(shí),也就是發(fā)生在安卓設(shè)備運(yùn)行應(yīng)用時(shí),而不是在開發(fā)期間。具體來說,是發(fā)生在 JIT 和 AOT 的過程中的。

內(nèi)聯(lián)崩潰的場(chǎng)景  

1、特點(diǎn)和條件內(nèi)聯(lián)崩潰是一種 native 崩潰,有明確的 abort message,容易辨認(rèn),發(fā)生在以下場(chǎng)景:

  • 崩潰發(fā)生時(shí)一定在運(yùn)行 epg 插件(或者叫宿主插件),one 版本時(shí)不可能發(fā)生。
  • 只有 epg 插件有這個(gè)問題。投屏、設(shè)置、體育等所有功能插件沒有這個(gè)問題。
  • 只發(fā)生在 Android 9.0(P) 系統(tǒng)上。

觸發(fā)的概率較低,但在大量用戶的基礎(chǔ)上有一定量級(jí),奇異果的各個(gè)版本都能在 APM 中搜到這種崩潰。在 APM 上一直存在,但沒有針對(duì)性地統(tǒng)計(jì)過具體在 9.0 系統(tǒng)的崩潰率。

這個(gè)內(nèi)聯(lián)崩潰問題本地不容易復(fù)現(xiàn),需要長(zhǎng)時(shí)間運(yùn)行 one 版本才有可能觸發(fā)內(nèi)聯(lián),進(jìn)而在運(yùn)行插件版時(shí)發(fā)生崩潰。

這個(gè)內(nèi)聯(lián)崩潰是安卓插件化領(lǐng)域已知的問題,tinker 有公開分享的解決方案,但對(duì)于我們并不適用,后文會(huì)詳細(xì)說明。

2、崩潰現(xiàn)場(chǎng)Native 崩潰 abort message:

entrypoint_utils-inl.h:94] Inlined method resolution crossed dex file boundary: from void com.gala.video.plugincenter.download.downloader.DownloadManager$TaskHolder.progress(com.gala.video.module.plugincenter.bean.download.DownloadItem, long, long, long, b...

崩潰棧:

圖片

JIT、AOT、混合編譯  

1、JIT

JIT(Just-In-Time),也稱為即時(shí)編譯。是一種運(yùn)行時(shí)優(yōu)化技術(shù),虛擬機(jī)在運(yùn)行時(shí)將字節(jié)碼編譯為機(jī)器碼,從而提高執(zhí)行效率。在普通的 JVM 上就有 JIT 的存在,安卓的 Dalvik 與 ART 也都實(shí)現(xiàn)了 JIT。JIT 是運(yùn)行在 app 的進(jìn)程中的,有一個(gè)獨(dú)立的線程負(fù)責(zé)運(yùn)行 JIT。

2、AOT

AOT(Ahead-Of-Time),也稱為預(yù)編譯。注意這個(gè)預(yù)編譯是運(yùn)行在安卓設(shè)備中的,不是我們開發(fā)過程中的編譯。所謂預(yù)編譯,是指在安裝的時(shí)候進(jìn)行一次全量編譯,將字節(jié)碼轉(zhuǎn)換為機(jī)器碼,從而提高運(yùn)行速度。但是 AOT 由于進(jìn)行了全量編譯,會(huì)生成很大的二進(jìn)制文件,占用更多的空間,并且安裝過程比較慢,尤其是ROM升級(jí)后,所有 APP 都要重來一遍AOT,會(huì)陷入漫長(zhǎng)的等待。

3、混合編譯

由于 AOT 有占用空間大和安裝時(shí)間長(zhǎng)的缺點(diǎn),從 Android N(7.0) 開始,ART 中引入了混合編譯的模式。混合編譯即將“解釋執(zhí)行”、“JIT”與“AOT”這三種代碼執(zhí)行模式按照一定的規(guī)則來切換,平衡運(yùn)行效率、內(nèi)存使用與CPU耗電。在應(yīng)用安裝時(shí)不做 AOT 編譯,直接以解釋方式執(zhí)行,達(dá)到快速啟動(dòng)的效果。在應(yīng)用運(yùn)行時(shí)分析運(yùn)行過的代碼以及“熱代碼”,進(jìn)行 JIT 編譯。同時(shí)將哪些代碼屬于“熱代碼”的記錄存儲(chǔ)下來,等設(shè)備空閑與充電時(shí),使用 AOT 編譯這份配置中的“熱代碼”。

圖片

02原因分析?

abort message  

根據(jù) abort message:

entrypoint_utils-inl.h:94] Inlined method resolution crossed dex file boundary…

?我們找到 entrypoint_utils-inl.h 文件的 94 行:

圖片

這段代碼和注釋的大概意思是,如果被內(nèi)聯(lián)的函數(shù)與調(diào)用它的函數(shù)不在同一個(gè) dex 中,在執(zhí)行這個(gè)內(nèi)聯(lián)函數(shù)的時(shí)候,就會(huì)主動(dòng)觸發(fā)崩潰。

如果一個(gè)應(yīng)用沒有使用任何插件技術(shù),那么是不可能產(chǎn)生這個(gè)問題的。因?yàn)橐粋€(gè)函數(shù)被內(nèi)聯(lián)的前提條件之一就是調(diào)用它的函數(shù)與它在同一個(gè) dex 中。這看似是一個(gè)矛盾,但因?yàn)橛辛瞬寮夹g(shù),就讓這個(gè)場(chǎng)景有可能出現(xiàn)了。

插件化  

先從奇異果的插件化架構(gòu)說起:

圖片

圖中 one 版本就是沒使用宿主插件的版本,用戶剛安裝好我們的 apk 或者剛升級(jí) apk 后啟動(dòng)就是這個(gè)版本。插件版本是下載并安裝了宿主插件,并且重啟后加載了宿主插件的版本。

我們只需考慮宿主插件,而不考慮其他的子插件,因?yàn)檫@些子插件始終是獨(dú)立的 dex,不可能與其他模塊的產(chǎn)生內(nèi)聯(lián)的相互調(diào)用。

由于這個(gè)問題與 dex 文件有關(guān),所以下面從 dex 的角度說明插件相關(guān)架構(gòu)。

圖片

可以簡(jiǎn)單地理解 one 版本只有一個(gè)dex 文件,而每一個(gè)插件都是一個(gè)額外的 dex 文件。宿主插件(也就是epg插件)也是額外的一個(gè) dex 文件,這個(gè) dex 文件就在我們每次部署插件時(shí)上傳的 apk 內(nèi)。

從功能的角度理解,將插件升級(jí)后不會(huì)更新的部分稱為 host 部分,epg 插件的所有內(nèi)容稱為 epg 部分。

在 one 版本運(yùn)行時(shí),epg 部分與 host 部分屬于同一個(gè) dex,所以從 host 調(diào)用到 epg 的函數(shù)調(diào)用,是可能被內(nèi)聯(lián)的。經(jīng)過插件升級(jí),epg 部分是新的 dex,host 還是原來的 dex,從 host 調(diào)用到 epg 的函數(shù)調(diào)用就跨越了兩個(gè) dex。因此,在插件升級(jí)后可能會(huì)產(chǎn)生跨越 dex 的內(nèi)聯(lián)調(diào)用,也就觸發(fā)了崩潰。

host 不會(huì)也不能直接調(diào)用 epg。host 會(huì)提供一些接口,接口的方法中有一些回調(diào)類型接口,epg 實(shí)現(xiàn)了回調(diào)接口,然后這些接口被 host 內(nèi)部調(diào)用,就發(fā)生了 host 到 epg 的間接調(diào)用。

從模塊設(shè)計(jì)角度看,epg 屬于業(yè)務(wù)模塊,依賴一些屬于 host 部分的底層庫(kù),可直接調(diào)用。Host 部分不依賴業(yè)務(wù),也就是不依賴 epg,沒有直接調(diào)用,但有回調(diào)。出現(xiàn)內(nèi)聯(lián)崩潰的調(diào)用都是從 host 回調(diào)到 epg 的方法。

圖片

回調(diào)示例

為什么主動(dòng)崩潰  

1、原因

因?yàn)榭?dex 內(nèi)聯(lián)的調(diào)用一旦出現(xiàn),就意味著被內(nèi)聯(lián)的機(jī)器碼是“歷史”代碼,可能與“新”的另一個(gè) dex 中的字節(jié)碼不匹配。相當(dāng)于生成了錯(cuò)誤的機(jī)器碼,與實(shí)際的字節(jié)碼對(duì)應(yīng)不上。這就可能產(chǎn)生各種無法預(yù)測(cè)的錯(cuò)誤。

當(dāng)然,如果插件 dex 與 one 版本的 dex 內(nèi)容一模一樣,理論上是不會(huì)有問題的。插件 dex 修改的內(nèi)容越多,就越可能出現(xiàn)這個(gè)問題。從長(zhǎng)期的代碼演變角度來說,出現(xiàn)問題是必然的,出現(xiàn)了多少問題是概率性的。

在 9.0 上系統(tǒng)主動(dòng)崩潰是安卓系統(tǒng)的一種主動(dòng)防御,用“自殺”來防止發(fā)生跨 dex 內(nèi)聯(lián)可能導(dǎo)致的“無法預(yù)測(cè)”的程序行為。在早于 9.0 的版本上谷歌可能還沒有發(fā)現(xiàn)這種跨 dex 內(nèi)聯(lián)的問題,然后在 10.0 的版本又放寬了限制,可能認(rèn)識(shí)到了跨 dex 內(nèi)聯(lián)是低概率事件,還是讓玩弄 dex 的玩家自己負(fù)責(zé)吧。

所以,9.0 inline 問題不只是在 9.0 上的顯性崩潰問題,在 7.0 以上除了 9.0 以外的其他版本上,仍然可能會(huì)有隱性的“無法預(yù)測(cè)”的程序行為,可能是 crash,也可能是邏輯上的異常。如果通過阻止內(nèi)聯(lián)的方式解決了 9.0 inline 崩潰問題,也可以順帶解決跨 dex 內(nèi)聯(lián)在所有系統(tǒng)版本上的潛在問題。

2、“無法預(yù)測(cè)”的錯(cuò)誤

在內(nèi)聯(lián)生成的機(jī)器碼中,并不一定將整個(gè)調(diào)用鏈上的所有字節(jié)碼都生成了機(jī)器碼。比如A.a() 調(diào)用 B.b(),B.b() 調(diào)用 C.c() 。一種可能的情況是:A.a() 內(nèi)聯(lián)了 B.b(),但對(duì) C.c() 的調(diào)用沒有內(nèi)聯(lián)。

這種情況下,在 A.a() 中執(zhí)行C.c() 的時(shí)候會(huì)從機(jī)器碼跳回虛擬機(jī)執(zhí)行 ,然后就得走類的加載和方法的解析(resolve)的流程:找到 解析緩存(DexCache[]),并根據(jù)緩存中的偏移指針,找到這個(gè)類,進(jìn)而找到方法去執(zhí)行。注意需要兩個(gè)值才能找到類,一個(gè)是 DexCache 數(shù)組,另一個(gè)是這個(gè)數(shù)組中的類 C 的偏移指針(下標(biāo))。

這個(gè) DexCache 數(shù)組是與dex 文件相關(guān)聯(lián)的,不同的 dex 文件 DexCache 數(shù)組也不一樣。在編譯生成的機(jī)器碼中,使用的是一個(gè)函數(shù)指針直接跳到了 native 版本的 FindClass,得到的結(jié)果是保證正確的。也就是說在運(yùn)行插件版時(shí)能正確獲取到插件 dex 的 DexCache[]。

然而 DexCache 數(shù)組中的偏移量卻是“寫死”在機(jī)器碼中的立即數(shù),也就是dex2oat 編譯后直接寫在指令中的。用舊 DexCache 數(shù)組中的偏移量,在新 DexCache 數(shù)組中查找 Class,最后得到的不一定是正確的 Class。在這個(gè) native 的層次上,不會(huì)有 ClassCastException 拋出來阻止進(jìn)一步發(fā)生錯(cuò)誤,只會(huì)默默執(zhí)行直到出現(xiàn)問題。比如調(diào)用方法對(duì)應(yīng)不上導(dǎo)致崩潰、static 變量找不到返回 null 等等。

圖片

03解決方案

業(yè)界方案——Tinker  

Tinker 最終采用的應(yīng)對(duì)方案是去掉 ART 環(huán)境下的合成增量 dex 的邏輯,直接合成全量的 NewDex,這樣除了 loader 類,所有方法統(tǒng)一都用了 NewDex 里的,也就不怕有方法被內(nèi)聯(lián)了。——摘自《ART 下的方法內(nèi)聯(lián)策略及其對(duì) Android 熱修復(fù)方案的影響分析 》

Tinker 的方案相當(dāng)于找到了一個(gè)切面,將不可能互相調(diào)用的 loader 與其他 Class 切開,將所有類分成兩個(gè)集合。熱修復(fù)后,通過合成 dex 的方式,將“其他Class”部分完全替換掉,“其他Class” 的內(nèi)部就沒有了內(nèi)聯(lián)問題,并且 loader 部分與“其他 Class”部分是沒有相互調(diào)用的,也就不可能內(nèi)聯(lián)。因此 Tinker 是通過整體架構(gòu)的方式規(guī)劃 Class 避免內(nèi)聯(lián)。

我們的方案  

在不修改插件架構(gòu)的前提下,無法使用 Tinker 的方案。沒有一個(gè)切面可以保證宿主和插件不互相調(diào)用,例如我們的下載模塊是放在插件中心內(nèi)的。

既然無法通過 dex 分割的方式預(yù)防內(nèi)聯(lián),那我們只能選擇其他方式預(yù)防或阻止內(nèi)聯(lián)。阻止內(nèi)聯(lián)應(yīng)該在 one 版本上阻止,因?yàn)槭?one 版本上發(fā)生的內(nèi)聯(lián)引發(fā)的問題,也就是說要處理的是 apk 升級(jí)的 apk,而不是插件升級(jí)包 apk。

內(nèi)聯(lián)的目的是對(duì)程序的優(yōu)化,而且也確實(shí)能提升應(yīng)用的執(zhí)行效率,我們沒必要,也不應(yīng)該,也很難在整個(gè)應(yīng)用范圍內(nèi)全面地禁止內(nèi)聯(lián)。上文說過我們的內(nèi)聯(lián)方向是從 host 調(diào)用 epg,epg 實(shí)現(xiàn)了 host 提供的接口被 host 調(diào)用。在 APM 上,目前捕獲到了兩個(gè)調(diào)用的內(nèi)聯(lián)引發(fā)的崩潰,這種調(diào)用的數(shù)量不會(huì)很大,我們是否能夠精確找到這些調(diào)用并加以處理呢?

1、精確定位內(nèi)聯(lián)調(diào)用

我們可以簡(jiǎn)單地手動(dòng)檢查 host 調(diào)用epg 的代碼,但這種方式肯定是不完備的,因?yàn)槲覀兡芸吹降拇a只是一小部分,還有隱藏在 jar 包等無法直接看到的部分。如果未來代碼發(fā)生了改變。即使只是重構(gòu),也有可能使原來不內(nèi)聯(lián)的調(diào)用變成內(nèi)聯(lián)的調(diào)用,因此手動(dòng)查找和分析并不靠譜,必須有一種自動(dòng)搜索方式來精確查找。

舉個(gè)例子,觸發(fā)內(nèi)聯(lián)的條件之一就是被內(nèi)聯(lián)的函數(shù)的字節(jié)碼的數(shù)量不能超過一個(gè)最大值,如果重構(gòu)簡(jiǎn)化了代碼可能字節(jié)碼數(shù)量就會(huì)減少,從不會(huì)被內(nèi)聯(lián)變成可能被內(nèi)聯(lián)。

在編譯過程中直接讀取字節(jié)碼,在字節(jié)碼中搜索可能發(fā)生內(nèi)聯(lián)的調(diào)用語句,收集這些調(diào)用的信息,再根據(jù)這些信息通過某種方式修改字節(jié)碼,達(dá)到阻止內(nèi)聯(lián)的方式。

我們的 xpluin 插件中已經(jīng)實(shí)現(xiàn)了一些 ASM 腳手架來修改字節(jié)碼,可以直接選擇這些工具來讀取和改寫字節(jié)碼。

收集好所有的可能內(nèi)聯(lián)的調(diào)用語句后,就可以考慮使用哪種方式來阻止內(nèi)聯(lián)。

2、阻止內(nèi)聯(lián)的方案以下條件必須都滿足才能觸發(fā)內(nèi)聯(lián):

  1. App 不是 Debug 版本的;
  2. 被調(diào)用的方法所在的類與調(diào)用者所在的類位于同一個(gè) Dex;(注意,符合 Class N 命名規(guī)則的多個(gè) Dex 要看成同一個(gè) Dex)
  3. 被調(diào)用的方法的字節(jié)碼條數(shù)不超過 dex2oat 通過--inline-max-code-units指定的值,6.x 默認(rèn)為 100,7.x 默認(rèn)為 32;
  4. 被調(diào)用的方法不含 try 塊;
  5. 被調(diào)用的方法不含非法字節(jié)碼;
  6. 對(duì)于7.x版本,被調(diào)用方法還不能包含對(duì)接口方法的調(diào)用。(invoke-interface指令)

——摘自《ART 下的方法內(nèi)聯(lián)策略及其對(duì) Android 熱修復(fù)方案的影響分析》

雖然這些條件只要打破一個(gè)就可以阻止內(nèi)聯(lián),但實(shí)際上可以利用的點(diǎn)并不多。比如,我們不可能將線上包改為 debug 版本;我們也不可能插入一些非法字節(jié)碼;我們更不可能增加字節(jié)碼數(shù)量。對(duì)我們可能有用的只有 2 和 4 了,針對(duì) "2. dex 拆分" 和 "4. try塊",有兩種方案如下:

ClassLoader 拆分方案

這個(gè)方案是利用了這樣一個(gè)隱藏規(guī)則,即使是同一個(gè) dex,由不同的 ClassLoader 加載的類,也不算同一個(gè) dex 內(nèi)。

由于 ClassLoader 的雙親委派模型規(guī)則,一個(gè) Class 直接引用的其他 Class,直接走 native 層的查找路徑,不走 Java ClassLoader。因此不受約束的 Class 引用結(jié)構(gòu),使用多個(gè) ClassLoader 會(huì)產(chǎn)生雙向引用結(jié)構(gòu),徒增 ClassLoader 的復(fù)雜度。

考慮到自定義 ClassLoader 在 host 范圍內(nèi),如果出問題,host 代碼無法通過插件升級(jí)修復(fù),風(fēng)險(xiǎn)較大,因此最終并沒有采用這個(gè)方案。

插入 try-catch 方案

ClassLoader 方案是以類為最小單位處理函數(shù)內(nèi)聯(lián),而插入 try 塊的是針對(duì)函數(shù)的。在收集好調(diào)用信息之后,就非常簡(jiǎn)單了,在 epg 中找到需要插入 try 塊的函數(shù),在函數(shù)中插入一個(gè) try 塊即可。

搜索"可能內(nèi)聯(lián)的調(diào)用"編譯時(shí)算法  

使用 AOP 的方式,在編譯期 gradle Transform 階段找到所有的需要修改的方法,通過 ASM 修改字節(jié)碼,在這些要修改的方法中插入一條 try 語句。這個(gè)問題的特點(diǎn):輸入規(guī)模比較大,總共有 2W+ 個(gè)類。但解的數(shù)量很少,約 100 以內(nèi)(12.4 版本處理了 85 個(gè))。

算法簡(jiǎn)介:

圖片

插入的字節(jié)碼

圖片

為什么要插入這么復(fù)雜的一條語句呢?直接插入空的 try-catch 語句不行么?

不行,在由 java 字節(jié)碼轉(zhuǎn)換為dex 字節(jié)碼的階段,d8 會(huì)進(jìn)行一些優(yōu)化操作。如果 try {} 中是空的,那么不會(huì)生成任何代碼;如果是無意義的代碼,比如只定義了一個(gè)局部變量 int a = 0; 也會(huì)被優(yōu)化刪除掉。因此只能插入一些簡(jiǎn)單的有副作用的代碼。

04結(jié)論?

本文介紹了一種適合 TV 端的解決插件化內(nèi)聯(lián)崩潰的方法:通過查找可能的內(nèi)聯(lián)調(diào)用點(diǎn),在編譯期自動(dòng)插入字節(jié)碼阻止內(nèi)聯(lián)的觸發(fā)的方式來預(yù)防內(nèi)聯(lián)崩潰問題,適用于TV 端插件化框架不分割業(yè)務(wù) dex 的特點(diǎn)。目前該方法通過若干版本的驗(yàn)證已解決內(nèi)聯(lián)崩潰問題。?

責(zé)任編輯:未麗燕 來源: 愛奇藝技術(shù)產(chǎn)品團(tuán)隊(duì)
相關(guān)推薦

2018-10-12 14:34:13

2025-01-07 16:00:00

Kubernetes云原生Pod

2011-11-30 13:59:17

JavaJVM

2011-05-24 11:26:11

2009-07-22 17:37:06

ASP.NET Ses

2019-05-22 09:51:28

網(wǎng)絡(luò)故障

2009-07-10 14:32:06

JVM崩潰

2015-03-18 10:35:13

虛擬化監(jiān)測(cè)虛擬化策略虛擬化解決方案

2022-11-07 13:59:05

Android插件化框架

2009-04-13 10:58:08

RapidRecoveProtectDriv解決方案

2024-11-08 13:47:35

中文亂碼配置

2010-08-27 14:35:37

IEFirefox兼容

2011-08-22 15:31:51

SQL Servermssqlserver數(shù)據(jù)庫(kù)復(fù)制

2012-03-09 13:57:40

華為無線模塊消費(fèi)電子

2020-03-05 09:09:18

緩存原因方案

2023-12-01 15:58:00

Kubernetes集群DevOps

2024-08-05 10:40:58

2013-10-31 15:20:06

2025-03-25 01:00:00

2010-04-26 16:31:09

Oracle SQL
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 黄色片免费看视频 | 天堂一区二区三区四区 | 免费特级黄毛片 | 国产精品久久久久久久免费大片 | 中文字幕日韩一区 | 中文字幕日韩欧美一区二区三区 | 精品国产乱码久久久久久蜜臀 | 亚洲欧洲一区 | 国产观看 | 中文在线一区 | 精品国产乱码一区二区三区 | 岛国毛片在线观看 | 国产精品美女一区二区三区 | 一区二区三区小视频 | 亚洲高清一区二区三区 | 一级毛片视频在线 | 密乳av| www.久久久| 免费黄色a级毛片 | 国产精品免费观看 | 高清亚洲| 日韩视频一区二区三区 | 六月成人网 | 一级午夜aaa免费看三区 | 亚洲精品乱码久久久久久久久久 | 国产91在线 | 欧美 | 中文字幕一区二区三区精彩视频 | 午夜色婷婷 | 欧美一级在线免费观看 | 波多野结衣精品在线 | 国产免费拔擦拔擦8x高清 | 久久久精品影院 | 欧美精品一二区 | 国产成人精品一区二区三区在线 | 91精品国产91久久久久久最新 | 中文字幕精品一区二区三区精品 | 久久久久国产一级毛片 | a欧美 | 国产午夜三级一区二区三 | 五月免费视频 | 久久综合av |