javascript
【腾讯Bugly干货分享】JSPatch 成长之路
本文來自于騰訊bugly開發(fā)者社區(qū),非經(jīng)作者同意,請勿轉(zhuǎn)載,原文地址:http://dev.qq.com/topic/579ef...
Dev Club 是一個交流移動開發(fā)技術(shù),結(jié)交朋友,擴展人脈的社群,成員都是經(jīng)過審核的移動開發(fā)工程師。每周都會舉行嘉賓分享,話題討論等活動。
本期,我們邀請了騰訊WXG iOS開發(fā)工程師——bang 陳振焯,為大家分享《JSPatch成長之路》。
如何加入 Dev Club?
移動端開發(fā)經(jīng)驗 >= 2 年,微信掃描下方群管理微信二維碼,備注姓名-公司(或產(chǎn)品) 申請加入。
分享內(nèi)容簡介:
JSPatch 是 iOS 上的動態(tài)更新框架,只需要引入小小的引擎文件,就可以用 JS 調(diào)用和替換任意 OC 方法。目前被普遍用于實時修復(fù) bug,已有超過2500個 APP 接入,本次分享介紹 JSPatch 發(fā)展過程中遇到的問題和解決思路。
(此內(nèi)容已在 GMTC 線下分享過,本次重新整理為線上分享)
內(nèi)容大體框架:
起步:介紹 JSPatch 的誕生和當(dāng)時碰到的難題
發(fā)展:介紹 JSPatch 如何補全周邊功能變得更好用
下一步:介紹 JSPatch 下一步的計劃
分享人介紹:
bang 陳振焯 廣州研發(fā)部 目前負(fù)責(zé)開發(fā)微信讀書iOS端,博客 http://blog.cnbang.net
下面是本期分享內(nèi)容整理
大家好,我是 bang,目前在廣州研發(fā)部做微信讀書 iOS 端,今天分享的主題是《JSPatch 成長之路》。
我在去年5月發(fā)布了 JSPatch (https://github.com/bang590/JS...?這個開源庫,現(xiàn)在廣泛應(yīng)用于 iOS 的熱修復(fù),今天分享一下 JSPatch 過去一年以來的成長。
分享共分為三個部分:
起步 —— 介紹JSPatch的誕生和當(dāng)時碰到的難題
發(fā)展 —— 介紹JSPatch如何補全周邊功能變得越來越好用
下一步 —— 介紹JSPatch下一步的計劃
一、起步
先說下起步階段。當(dāng)時碰到的一個問題是:APP 線上 bug 修復(fù)周期長,成本高,版本發(fā)布出去后,發(fā)現(xiàn)一個 bug,要修復(fù)這個 bug 就必須得另外發(fā)一個版本,也就是要經(jīng)歷:測試——打包——發(fā)布——審核——用戶下載,這一系列過程,成本非常高,最后還很難讓所有用戶都升級上來。
當(dāng)時業(yè)界已有一個解決方案,叫 waxPatch,它是在APP里嵌入 lua 引擎,然后通過 OC 的 runtime 接口在 lua 里調(diào)用和替換 OC 方法,這樣就可以下發(fā) lua 腳本替換原生代碼,動態(tài)修復(fù) bug。
waxPatch: https://github.com/mmin18/Wax...
這是個不錯的方案,但當(dāng)時的 waxPatch 存在很多缺陷:
首先是 wax 已經(jīng)多年不維護了,導(dǎo)致不支持一些 block/64 位等新特性,此外當(dāng)時 wax 還有文檔不足,測試不足,線程不安全,難以調(diào)試等坑。
于是開始探求更好的解決方案。很容易想到如果用 JavaScript 做這個事情的話,相對 lua 原生就有一些優(yōu)勢:
iOS 里已內(nèi)置 JavascriptCore 引擎,無需再另外嵌入。
JS 在終端應(yīng)用廣泛,很多混合開發(fā)內(nèi)嵌 H5 頁面就是用 JS。
符合蘋果審核規(guī)則,蘋果在文檔里說明不可以下載可執(zhí)行的代碼,由 JavascriptCore 執(zhí)行的除外。
那么有沒有人試過這樣做呢?用 Javascript 調(diào)用和替換 OC 方法,當(dāng)然是有的。
在當(dāng)時有一個開源庫 JavascriptBridge (https://github.com/kishikawak..., 它可以用 JS 調(diào)用 OC 接口。?不過它用的是 JavascriptCore 原生的接口做的,需要事先在 OC 里定義好要調(diào)用的接口,沒有事先定義的不能調(diào),這導(dǎo)致它的實現(xiàn)很臃腫,因為要在 OC 定義大量的方法。此外它也不能替換 OC 方法,實用性很低。
當(dāng)時國外還有一個熱補丁服務(wù)叫 rollout (http://rollout.io)。 它是一個服務(wù)平臺,底層也是用 JS 調(diào)用和替換 OC 方法去實時修復(fù) bug,不過它不是開源的,只能在這個平臺上用,另外它的 JS 寫法是比較復(fù)雜的,看看這個例子就知道,這導(dǎo)致它不得不在平臺上做一些便捷的功能,把一些常用的操作封裝起來,減少使用者寫代碼。
總的來說,當(dāng)時并沒有一個更好的方案,于是想自己造個。
當(dāng)時期望做到的效果是這樣的:
我在 JS 寫 UIView.allOC(), 然后傳給 JavascriptCore 執(zhí)行,JavascriptCore 把我要調(diào)用的信息,這里類名是 UIView,類方法名是 alloc 傳遞給 OC,OC runtime 就可以找到這個類和方法進行調(diào)用。這是最基本的一個語句調(diào)用。
實際上當(dāng)時實現(xiàn)這個最基本的調(diào)用就遇到一個檻,在 JS 里這條語句根本無法執(zhí)行:
要讓這條語句在 JS 環(huán)境中可以執(zhí)行,在 JS 的語言規(guī)則下,UIView 必須是一個對象,alloc 必須這個對象的一個方法。
也就是說要像這樣定義后才可以執(zhí)行:
UIView 必須是一個對象這點沒問題,在調(diào)用前定義就可以,但 UIView 的方法必須在調(diào)用前定義就很糟糕,這意味著如果你想調(diào)用任意 UIView 的方法,你就需要提前把所有 UIView 的方法都找出來,每一個方法都要預(yù)先定義好。
也就是說在使用UIView之前,需要先去 OC 把UIView所有方法找出來,然后構(gòu)建UIView對象,每個方法都在這個對象里生成對應(yīng)的函數(shù),然后你才可以調(diào)用UIView的任意方法。
JSPatch 在開發(fā)時就嘗試過這種方案,后來發(fā)現(xiàn)這些對象的方法太多了,僅 NSObject 基類的實例方法就有830個,類方法有118個,這導(dǎo)致在JS生成的對應(yīng)的對象占用內(nèi)存極高,NSObject就占了1.3M,UIView占2M。這根本不可用。
對此我還進行了一些優(yōu)化嘗試,例如去除掉里面的下劃線開頭的私有方法,在 JS 構(gòu)造繼承鏈共用基類方法。但這些優(yōu)化都沒多少效果,占用內(nèi)存依舊很高。當(dāng)時就覺得不太可能實現(xiàn)。
實際上當(dāng)時我陷入了一個思維定勢,做終端久了,思維停留在 iOS 的 OC 世界,寫代碼必須遵守語言的規(guī)則,上述的困難也是在遵守 JS 語言規(guī)則這個前提下碰到的。
如果有方法不遵守語言規(guī)則呢?實際上在 JS 界,有個很常用的伎倆,就是預(yù)編譯:
也就是我們寫的腳本不直接拿給 JS 引擎執(zhí)行,而是進行一些轉(zhuǎn)換后才執(zhí)行,在現(xiàn)代框架這個用法很常見, react/vue 都用了,甚至還有像 coffieScript 這樣把 JS 完全換成另一種語言的做法。
想到這一點,剛才的問題就很好解決了。
只需要把所有函數(shù)調(diào)用在執(zhí)行前都替換一遍,變成去調(diào)用一個固定的 __c 函數(shù), 這個 __c 函數(shù)模擬了 ruby/lua 等語言的元方法機制,對方法調(diào)用進行轉(zhuǎn)發(fā)。
還是以調(diào)用 UIView 的 alloc 方法為例,這個語句在執(zhí)行之前會被替換為調(diào) UIView 的 __c 方法,把 "alloc" 作為字符串參數(shù)穿進去,在 __c 方法里判斷調(diào)用者 UIView 是不是 OC 對象。如果是,就把類名和傳進來的方法名傳到 OC 層進行調(diào)用,如果不是,就調(diào)用回 JS 這個對象的方法。
這樣做簡潔高效地解決了前面的問題,不需要去 OC 遍歷每個類的方法,不需要存儲這些方法,就可以調(diào)用任意 OC 方法,只需要給 JS 基類定義一個 __c 方法就可以了。正則替換后無論調(diào)用 OC 的什么方法,都不會有語法錯誤,因為都變成調(diào)用這個 __c 方法,在這個 __c 方法里做處理去 OC 層調(diào)用相應(yīng)的方法就行了。
使用這種方案后內(nèi)存的占用下降了 99%,甚至更多,也使 JSPatch 的使用成為可能,這是 JSPatch 最核心的一點。
解決這個核心問題后,后面就是細(xì)化功能了,JSPatch 發(fā)布以后一直在完善,包括最基本的調(diào)用和替換OC方法,還有支持64位,支持 block,支持包括 c指針/Class/結(jié)構(gòu)體等類型,支持 c函數(shù)的調(diào)用等,這里面的細(xì)節(jié)原理我覺得看文章會比較清晰,相關(guān)文章都可以在 github wiki (https://github.com/bang590/JS...?上找到,這里就不多說了。
二、發(fā)展
接下來說說 JSPatch 是怎樣進行進一步發(fā)展的。
在完善 JSPatch 的同時,我也在想,如何把 hotfix 做得更好。
主要有兩個思路:
降低使用門檻
提高使用效率
我們一個點一個點來看對這兩個問題是怎么做的。
首先 JSPatch 在易用性上一直堅持著一個理念,就是 keep it simple and tiny,用中文說就是保持精巧,保持好用。JSPatch 從開源到現(xiàn)在一年多,增加和完善了很多功能,但它的使用方式和接口都沒有變過,一直以來都是只有三個文件,拖入項目直接可以使用,也會很謹(jǐn)慎地新增接口,不會影響到舊接口的使用,不會出現(xiàn)同一份代碼在舊版本能用,在新版本不能用的情況,在易用性上降低使用門檻。
另一個問題是安全問題。
JSPatch 可以調(diào)用和替換任意 OC 方法,權(quán)限很大,如果在傳輸過程中被第三方攻擊,替換了下發(fā)的代碼去執(zhí)行,會對用戶和 APP 本身造成很大傷害。如果每個接入 JSPatch 的人都要考慮這個安全問題,接入門檻就會很高,也可能會因為考慮不周全導(dǎo)致 APP 處于危險狀態(tài)。
對此當(dāng)時詳細(xì)考慮了安全策略。對這種情況:
最簡單的方案是直接對腳本加密,后臺使用固定密鑰加密腳本后下發(fā),客戶端使用同樣的密鑰解密。這種方案的優(yōu)點是簡單,缺點是這個密鑰必須存在客戶端,黑客很容易破解拿到這個密鑰,然后通過傳輸過程第三方攻擊,下發(fā)同樣用這個密鑰加密的惡意代碼,就沒有安全可言了。
第二個方案是讓腳本通過 https 傳輸,這個方案的優(yōu)點是安全性高,只要客戶端對證書進行過足夠的驗證,就能很好地保證安全性。缺點是這個方案門檻高,部署繁瑣,需要購買證書,對一些中小 APP 來說可能難以接受,并且如果用戶手機信任了一些惡意證書,也還是存在被攻擊的危險。
第三個方案是使用RSA簽名驗證。
整個流程是這樣:
第一步服務(wù)端計算腳本文件的MD5值,用存在服務(wù)端的私鑰對這個MD5值進行加密,然后把這個MD5值和腳本一起打包下發(fā)給客戶端。客戶端拿到腳本和加密后的MD5值,用存在客戶端的公鑰進行解密,拿到服務(wù)端計算的MD5值,本地再計算一遍腳本文件的MD5值,對比這兩個值是否一致,若一致則表示傳輸過程中沒有被篡改。
如果第三方要截獲請求下發(fā)惡意腳本,第三方必須用私鑰加密這個惡意腳本的MD5值一起下發(fā),才能通過驗證執(zhí)行,只要服務(wù)端不被攻破,第三方就沒有私鑰,也就無法進行篡改。
可以看到這第三個方案門檻低,通用性高,部署簡單,安全性也高,對服務(wù)端和客戶端都沒有什么特殊要求。
我把這一套安全方案做成一個組件,叫 JPLoader,也開源在 JSPatch 項目上(https://github.com/bang590/JS..., 需要部署 JSPatch 的同學(xué)可以直接使用這套組件,解決安全性問題,客戶端的工作就完成了,只剩下后端的工作。
前面把安全性問題解決了,只剩下后端的工作,但搭建后臺對使用者來說也是挺麻煩的事,特別是作為 iOS 開發(fā)者,在中小公司自己搭后臺麻煩,在大公司要后臺幫你搭也不容易,這又會導(dǎo)致使用 JSPatch 的門檻還是很高。
于是在想這部分工作能不能也幫使用者省了呢?
對此我搭建了 JSPatch 平臺 (http://JSPatch.com), 讓使用 JSPatch 的人不需要搭建后臺,直接通過平臺下發(fā)補丁代碼。
這個平臺幾個月前已經(jīng)開放注冊,現(xiàn)在所有人都可以使用。
在搭建這個平臺時,碰到一個問題值得分享一下,就是如何支持高并發(fā)?
由于 JSPatch 的補丁特性,補丁需要及時推送給用戶,也就是說至少需要在每次啟動時向服務(wù)端請求詢問 APP 是否有新的補丁,有的話下發(fā)執(zhí)行。這里詢問的請求量是很高的,單個 APP 可以控制,但平臺要面對多個 APP,累計起來的請求數(shù)量會非常多,并發(fā)會很高,怎樣支撐這樣的高并發(fā)?
正常來說這樣一個系統(tǒng)整體設(shè)計大致是這樣的:
平臺用戶把腳本放到平臺服務(wù)端,服務(wù)端的數(shù)據(jù)庫保存著腳本的各種信息和內(nèi)容,APP 客戶端向平臺發(fā)起請求詢問是否有新腳本,平臺服務(wù)端接收到請求后通過 CGI 處理請求參數(shù),根據(jù) APPkey 等參數(shù)從數(shù)據(jù)庫拿出這個 APP的信息,然后組裝數(shù)據(jù)告訴APP客戶端有沒有新腳本。
這里的詢問請求至少時 APP 每次啟動都要發(fā)一次請求,才能保證腳本的更新能盡快下發(fā)。請求量大時,這里從數(shù)據(jù)庫取出數(shù)據(jù)很容易成為整個系統(tǒng)的瓶頸,CGI 處理請求參數(shù)和組裝數(shù)據(jù)也要耗不少資源。
對此我改用了另一種方式:
平臺用戶上傳腳本到平臺服務(wù)器時,服務(wù)端除了把 APP 信息存在 DB 外,同時會另外上傳一份 JSON 靜態(tài)文件到靜態(tài)云服務(wù)器,JSON 里保存了當(dāng)前補丁的版本,而這個靜態(tài)資源的文件名是由 APPkey/APP 版本號組成的。
例如這里腳本補丁版本號是10,這個JSON靜態(tài)文件的內(nèi)容就是 {v:10}。可以想象靜態(tài)文件的訪問路徑就是:
http://JSPatch.com/{APPkey}/{APP_version}.json然后 APP 客戶端不再向平臺服務(wù)端發(fā)請求,而是向這個靜態(tài)資源服務(wù)器發(fā)請求,根據(jù) APPKey 和 APP 版本直接請求到這個 JSON 文件,里面帶的版本號信息就可以告訴 APP 腳本是否有更新。
整個流程就變成了:
APP 向靜態(tài)服務(wù)器詢問是否有新補丁,靜態(tài)服務(wù)器直接返回預(yù)先設(shè)置好的 JSON,就結(jié)束了。
這樣 APP 永遠(yuǎn)不會跟平臺服務(wù)器打交道,只需跟靜態(tài)資源服務(wù)器打交道,靜態(tài)資源的高并發(fā)處理起來就簡單得多,成本也低很多,現(xiàn)在有很多靜態(tài)資源云存儲,直接接入就可以了,以這些云存儲的能力,支持多高的并發(fā)都沒有問題,用戶量多大的 APP 接入都可以支撐到。就是這樣 JSPatch 平臺解決了高并發(fā)問題,可以投入使用。
接下來在開發(fā)效率上,有一個問題是轉(zhuǎn)換代碼效率低。
我們用 JSPatch 修復(fù) bug 時時以方法為單位進行替換的,若原方法有上百行,你的需求只是修改其中一兩行代碼,你也要把這上百行代碼人工翻譯成 JS 才行。對此我開發(fā)了JSPatch Convertor 這個工具,可以自動把 OC 代碼轉(zhuǎn)為 JSPatch 代碼,提升開發(fā)效率。
這個工具也開源在 github 上(https://github.com/bang590/JS..., 支持了大部分語法特性,但目前還做不到支持所有特性,像私有變量/靜態(tài)變量/宏這些還不支持,所以轉(zhuǎn)換后需要人工修改,但還是很大地提高了使用 JSPatch 的效率。
總結(jié)下來,在降低使用門檻上,JSPatch 保證了易用性,封裝了安全方案,提供了 JSPatch 平臺讓使用者可以直接接入,另外還有完善的文檔和解析文章保證使用無障礙。提高使用效率上,做了 JSPatch Convertor 自動轉(zhuǎn)換代碼,也內(nèi)置了一些擴展方便直接調(diào)用一些常用的 C函數(shù)。
經(jīng)過不斷發(fā)展,JSPatch 可以說是 iOS hotfix 的最佳解決方案。
目前大部分應(yīng)用都已經(jīng)接入使用,據(jù)不完全統(tǒng)計至少有 2500 個 APP 接入,經(jīng)過了的大用戶量的考驗。
三、下一步
接下來說說下一步的計劃,JSPatch 在 hotfix 上已經(jīng)做得不錯,目前下一步打算推動使用 JSPatch 開發(fā)功能模塊。
JSPatch 做這個事情跟 React Native 和 weex 這類方案比起來,會有一些優(yōu)勢:
首先 React Native 和 weex 都是從前端出發(fā)擴展到終端,是前端方案的延伸,他們的體系對于前端來說更熟悉,對于終端來說,意味著要重新學(xué)習(xí)前端的一套知識,學(xué)習(xí)成本較高,而 JSPatch 是從終端出發(fā),編碼體系也差不多是直譯 OC,學(xué)習(xí)成本較低。
第二點是 ReactNative 和 Weex 是比較大型的框架,環(huán)境配置都很復(fù)雜,也會增大不少安裝包的大小,如果說只想擴展實現(xiàn)一兩個小功能,接入這么大型的框架不合適。而 JSPatch 前面也說了,屬于微型框架,只有三個文件,也無需環(huán)境配置。
第三點是 ReactNative 和 Weex 的組件都是要一個個封裝好,難以復(fù)用現(xiàn)有的 OC 組件,并且他們都是大型框架,在未成熟階段框架本身實現(xiàn)上的坑會很多,而 JSPatch 可以直接復(fù)用所有 OC 現(xiàn)有組件,并且只是薄薄的轉(zhuǎn)接層,坑會較少。
但 JSPatch 要用于開發(fā)功能,有兩個問題:
開發(fā)效率較低
運行效率較低。
在開發(fā)效率上,我做了兩件事去提高,第一個是 JSPatchX 代碼補全插件 (https://github.com/bang590/JS...。
寫 JSPatch 代碼時并不像 OC 那樣有代碼補全,在調(diào)用 OC 長長的方法時效率會很低,而且用 JSPatch 寫功能時,不像 hotfix 那樣有對應(yīng)的 OC 代碼,也無法使用前面說的 JSPatchConvertor 進行轉(zhuǎn)換。于是做了 JSPatchX 去彌補這個缺陷,可以在 XCode 自動提示補全 JSPatch 代碼。
另一個是 Playground 即時刷新范例 (https://github.com/bang590/JS...
可以實時預(yù)覽 JSPatch 腳本執(zhí)行的結(jié)果,無需像原生代碼那樣每一次修改都要 build 重啟才能看到效果,這也是腳本語言的優(yōu)勢。使用者可以仿照這個 playground 的實現(xiàn),在開發(fā)功能時在自己的頁面實現(xiàn)這樣的即時刷新,這樣一定程度上提高了開發(fā)效率。
接下來看看運行效率。
JSPatch 寫功能時運行效率低,于是著手進行優(yōu)化,第一步是確定瓶頸,發(fā)現(xiàn)運行速度最慢的在于在 JS 調(diào)用 JS 上定義的新方法。
例如這里新定義了一個dribbbleView類,里面有個新方法renderItem,在 JS 里調(diào)用這個新方法時,速度很慢。
分析下這個調(diào)用過程:
主要問題在于這個新定義的方法與 OC 掛鉤,這一次普通的調(diào)用,需要在 JS 和 OC 之間不斷來回通信,不斷進行參數(shù)轉(zhuǎn)換,經(jīng)過這9個步驟后才能成功調(diào)用。
對此我通過一些手段做了優(yōu)化,把這樣的方法直接放在 JS 環(huán)境上,在 JS 調(diào)用這個方法時無需再與 OC 通信,整個調(diào)用流程就變成了只有兩步:
經(jīng)過這個優(yōu)化后,這樣的方法調(diào)用性能最高提高 700 倍,這才使 JSPatch 寫功能變成一件靠譜的事。
除此之外還做了一些其他優(yōu)化,包括提升新增 property 性能,提供跟定義 OC 類一樣的純 JS 類定義接口,自動轉(zhuǎn)換參數(shù)類型等,具體優(yōu)化細(xì)節(jié)可以在這篇文章(http://blog.cnbang.net/tech/3... 上看到。
我用 JSPatch 寫了個 Dribbble 客戶端 demo (https://github.com/bang590/JS...? 在 iPhone5C 上測試過,滑動性能沒有問題。
最后,可以從這個腦圖看出 JSPatch 的現(xiàn)狀,周邊設(shè)施仍在繼續(xù)建設(shè)中。
我今天的分享就到這里,謝謝。
問答環(huán)節(jié):
Q1: JSPatch 的底層原理跟 ReactNative 是不是差不多呢?有受到其啟發(fā)么?
JSPatch 的原理跟 ReactNative 是完全不一樣的,JSPatch 是 OC 方法調(diào)用和替換的一層轉(zhuǎn)接,ReactNative 并不會去調(diào)用和替換 OC 方法,它有自己的一套通信規(guī)則。
Q2: 本身基于OC runtime 對 Swift 的項目如何支持?
Swift 相關(guān)問題在 wiki 里有提到:?
只支持調(diào)用繼承自 NSObject 的 Swift 類
繼承自 NSObject 的 Swift 類,其繼承自父類的方法和屬性可以在 JS 調(diào)用,其他自定義方法和屬性同樣需要加 dynamic 關(guān)鍵字才行。
若方法的參數(shù)/屬性類型為 Swift 特有(如 Character / Tuple),則此方法和屬性無法通過 JS 調(diào)用。
Swift 項目在 JSPatch 新增類與 OC 無異,可以正常使用。
Swift 的原生類目前沒找到替換的方法,動態(tài)調(diào)用倒是可以實現(xiàn)。
Q3: JSPatch 運行一次就會把JS轉(zhuǎn)換為 OC 緩存起來?那我們可以利用它去做一些重復(fù)調(diào)用的事情?甚至用來開發(fā)?它的效率和原生相近吧?
會緩存一些 methodSignature,但還是得通過反射 (className->class->imp) 去找到要調(diào)用的方法,效率會比原生低。但一般程序的瓶頸不會在語言這里。
Q4: 對于 JSPatch 資源更新服務(wù)平臺還是表示一些擔(dān)憂,如果被別人攻破了,豈不是很多 APP 都受牽連了?
JSPatch 平臺就算平臺被人黑了,也無法對平臺上的 APP 下發(fā)惡意代碼。只要使用者用了自定義的 RSA 密鑰就可以了,只有使用者有私鑰,每次發(fā)布腳本都要使用這個私鑰,平臺不會保存它,詳情可見:http://JSPatch.com/DOCs/rsa
Q5: 現(xiàn)在 iOS 加快了審核速度,好像現(xiàn)在是24小時內(nèi)審核上線。那現(xiàn)在 JSPatch 前景還會好么?
審核只是一個環(huán)節(jié),測試/打包/發(fā)布/用戶下載,這些其他環(huán)節(jié)還是不可少,并且最大的問題還是是用戶下載更新不可控。
Q6: Swift 屬于靜態(tài)編譯類型,是不是可以利用類似 c函數(shù)替換的方法呢?像 fishhook 這樣的工具
fishhook 需要編譯時確定要替換的函數(shù)指針,并不能在運行時替換任意 c函數(shù)
Q7: 我看網(wǎng)上的一些介紹說 JSPatch 對小的 bug 修復(fù)好點,大的還是提交新的版本,但是我看您介紹使用靜態(tài)資源服務(wù)器管理.應(yīng)該不存在數(shù)據(jù)量大,并發(fā)的問題.這個您怎么看?
他指的大的 bug 應(yīng)該是要寫很多代碼才能修復(fù)的 bug 吧?這點應(yīng)該跟 JSPatch 開發(fā)效率問題有關(guān),對于大量的代碼他不想原生 OC 寫一套修復(fù),再用 JSPatch 寫一套,跟數(shù)據(jù)量和并發(fā)應(yīng)該沒什么關(guān)系。
Q8: 為何 JSPatch 上面,QQmail 沒有接入?有什么顧慮嗎?
因為QQ郵箱在 JSPatch 出現(xiàn)之前已接入 lua,剛出現(xiàn)時 JSPatch 還不是很成熟,團隊當(dāng)時想同時使用兩種方案作對比,時間久了也沒有再切換過來了。
Q9: 有沒有可能進一步提升 JSPatch convertor 的能力。最終發(fā)到直接打開 Xcode 項目,尋找依賴,通過語法語義分析等,將 OC 轉(zhuǎn)換為 JS
可以做到的,不過這事要投入很大精力,之前有搞過一個 demo,直接用 OC 寫 Patch,然后在執(zhí)行前轉(zhuǎn)換成 JSPatch 代碼,有一個開源庫 JSTalk (https://github.com/ccgus/JStalk) 有基本的 OC->JS 的轉(zhuǎn)換,但要做到好用還有很多工作。
Q10: 請問如果我的 APP 引入了 JSPatch, 但是產(chǎn)生 crash 的代碼并不是通過 JS 寫的, 而是原生的 OC 代碼, 那么 JSPatch 可以通過下發(fā) JS 腳本修復(fù)這種 crash 嗎, 如果可以的話, 原理是怎樣的?
可以,原理就是把導(dǎo)致 crash 出現(xiàn)的方法替換掉,OC 調(diào)用那個方法時轉(zhuǎn)成調(diào)用 JSPatch 里寫的替換的方法,就不會 crash 了
Q11: 有沒有意識到 JSPatch 的性能瓶頸最終都取決于 JavascriptCore 的性能?所以低端機永遠(yuǎn)是低性能,有沒有想過借鑒 JSX 做點事情呢?
JavascriptCore 的性能并沒有問題,性能瓶頸不是 JavascriptCore,目前來看瓶頸會是 OC 與 JS 通信時大對象的參數(shù)轉(zhuǎn)換,但這是可以避免的
Q12: JSPatch 效率怎么樣啊
效率可以試試上文說的 dribbbleDemo
Q13: 調(diào)試 JSPatch 時能不能打斷點,如何定位到 JS 的 crash 堆棧
可以斷點,文檔有寫:https://github.com/bang590/JS...
如果大家對本次分享還有問題,請按以下格式在DEV社區(qū)(dev.qq.com)發(fā)問答帖
發(fā)帖格式:【bang@DEV Club 你問我答】 “問題”
最后,歡迎大家關(guān)注 JSPatch 公眾號:JSPatchDev,會即時推送 JSPatch 最新信息以及相關(guān)技術(shù)文章:
更多精彩內(nèi)容歡迎關(guān)注bugly的微信公眾賬號:
騰訊 Bugly是一款專為移動開發(fā)者打造的質(zhì)量監(jiān)控工具,幫助開發(fā)者快速,便捷的定位線上應(yīng)用崩潰的情況以及解決方案。智能合并功能幫助開發(fā)同學(xué)把每天上報的數(shù)千條 Crash 根據(jù)根因合并分類,每日日報會列出影響用戶數(shù)最多的崩潰,精準(zhǔn)定位功能幫助開發(fā)同學(xué)定位到出問題的代碼行,實時上報可以在發(fā)布后快速的了解應(yīng)用的質(zhì)量情況,適配最新的 iOS, Android 官方操作系統(tǒng),鵝廠的工程師都在使用,快來加入我們吧!
總結(jié)
以上是生活随笔為你收集整理的【腾讯Bugly干货分享】JSPatch 成长之路的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C#】依赖注入及Autofac
- 下一篇: JSPatch地址