當前位置:首頁 » 安卓系統 » androidload

androidload

發布時間: 2023-07-23 06:34:54

❶ 【Android】Android中的類載入

前文: 【java】ClassLoader與雙親委派機制

Android中的類載入器有三種, DexClassLoader 、 PathClassLoader 、 BootClassLoader 。
其中 BootClassLoader 是系統啟動時預載入常用類的,一般使用不到。 DexClassLoader 、 PathClassLoader 都是繼承自 BaseDexClassLoader 。
但 DexClassLoader 和 PathClassLoader 並沒有重寫 BaseDexClassLoader 中的任何方法,所以源碼只需要看 BaseDexClassLoader 即可。

由於Android SDK並沒有包含 BaseDexClassLoader ,所以需要到源碼查詢網站查詢源碼,如下:

復制這個java文件到對應源碼文件夾下就可以在Android Studio中查看了。

通過調試可以看到,Android中普通類的載入器其實是 PathClassLoader 。追蹤 PathClassLoader.findClass 方法,即可獲取Android的類載入過程:

PathClassLoader.findClass -- 繼承自 --> BaseDexClassLoader.findClass()
-> BaseDexClassLoader.pathList.findClass()
-> DexPathList.dexElements.foreach { element.findClass() }
-> Element.findClass()
-> Element.dexFile.loadClassBinaryName()
-> DexFile.defineClass()

即類載入過程通過 BaseDexClassLoader.findClass 、 DexPathList.findClass 、 Element.findClass 、 DexFile.loadClassBinaryName ,最終會落到 DexFile.defineClass 方法中,然後就交給native層了。

其中需要注意的是,在 BaseDexClassLoader.findClass 的開頭有這么一段:

這段是在Android 10新加入的,據稱是為了實現 shared library 功能的,在之前的版本中沒有這一段。

在上一節中知道了,類載入的流程如下:
BaseDexClassLoader.findClass() ->
BaseDexClassLoader.pathList.findClass() ->
DexPathList.dexElements.foreach { element.findClass() } ->
Element.findClass() -> ...

看 DexPathList.findClass 方法:

可以發現, DexPathList 載入類的方法是遍歷 dexElements 數組依次載入,知道獲取到值為止。所以可以通過修改這個數組,把新的dex文件放在數組的前面,使其載入修改後的類,從而實現熱修復。

根據以上原理,寫下這個工具類,有效性待驗證:

❷ android 的native方法,在哪使用System.loadLib()方法

不是loadLib,是

static{
System.loadLibrary("你的庫名");
}

這個是在類被載入的時候載入的,也就是你的Test。你說的有些沒有使用load,是因為在系統啟動的時候so已經被載入了。你可以通過命令行看到系統裡面的很多so:

如果so被載入了,你就不需要再使用載入代碼,可以直接用native介面

❸ android loaddatawithbaseurl 和loarl的區別

在開發Android平台的互聯網應用時,經常會使用到WebView,好處主要有兩個,一是可以更改要展現的內容(包括樣式),二是可以實現部分功能的跨平台。

Android的WebView組件使用非常簡單,可以使用loadUrl()載入一個Url地址,也可以使用loadData()或 loadDataWithBaseURL()載入一段HTML代碼片段。loadUrl()的使用大家應該都沒有什麼問題,但是loadData()和 loadDataWithBaseURL()在使用上的差異可能有些人還不太清楚。
首先,從方法的定義來看:
public void loadData (String data, String mimeType, String encoding)
public void loadDataWithBaseURL (String baseUrl, String data, String mimeType, String encoding, String historyUrl)
loadDataWithBaseURL()比loadData()多兩個參數,可以指定HTML代碼片段中相關資源的相對根路徑,也可以指定歷史Url。兩個方法的其餘三個參數相同。

其次,兩個方法載入的HTML代碼片段有些不同,loadData()中的html data中不能包含'#', '%', '\', '?'四中特殊字元,這就為我們內嵌css等製造了些許麻煩,因為css中經常用'#', '%'等字元,需要如何處理呢?我們需要用UrlEncoder編碼為%23, %25, %27, %3f 。
/**
* Loads the given data into this WebView using a 'data' scheme URL.
* <p>
* Note that JavaScript's same origin policy means that script running in a
* page loaded using this method will be unable to access content loaded
* using any scheme other than 'data', including 'http(s)'. To avoid this
* restriction, use {@link
* #loadDataWithBaseURL(String,String,String,String,String)
* loadDataWithBaseURL()} with an appropriate base URL.
* <p>
* If the value of the encoding parameter is 'base64', then the data must
* be encoded as base64. Otherwise, the data must use ASCII encoding for
* octets inside the range of safe URL characters and use the standard %xx
* hex encoding of URLs for octets outside that range. For example,
* '#', '%', '\', '?' should be replaced by %23, %25, %27, %3f respectively.
* <p>
* The 'data' scheme URL formed by this method uses the default US-ASCII
* charset. If you need need to set a different charset, you should form a
* 'data' scheme URL which explicitly specifies a charset parameter in the
* mediatype portion of the URL and call {@link #loadUrl(String)} instead.
* Note that the charset obtained from the mediatype portion of a data URL
* always overrides that specified in the HTML or XML document itself.
*
* @param data a String of data in the given encoding
* @param mimeType the MIME type of the data, e.g. 'text/html'
* @param encoding the encoding of the data
*/
public void loadData(String data, String mimeType, String encoding) {
checkThread();
mProvider.loadData(data, mimeType, encoding);
}
/**
* Loads the given data into this WebView, using baseUrl as the base URL for
* the content. The base URL is used both to resolve relative URLs and when
* applying JavaScript's same origin policy. The historyUrl is used for the
* history entry.
* <p>
* Note that content specified in this way can access local device files
* (via 'file' scheme URLs) only if baseUrl specifies a scheme other than
* 'http', 'https', 'ftp', 'ftps', 'about' or 'javascript'.
* <p>
* If the base URL uses the data scheme, this method is equivalent to
* calling {@link #loadData(String,String,String) loadData()} and the
* historyUrl is ignored.
*
* @param baseUrl the URL to use as the page's base URL. If null defaults to
* 'about:blank'.
* @param data a String of data in the given encoding
* @param mimeType the MIMEType of the data, e.g. 'text/html'. If null,
* defaults to 'text/html'.
* @param encoding the encoding of the data
* @param historyUrl the URL to use as the history entry. If null defaults
* to 'about:blank'.
*/
public void loadDataWithBaseURL(String baseUrl, String data,
String mimeType, String encoding, String historyUrl) {
checkThread();
mProvider.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
}

❹ android webview中的loadUrl方法是get請求還是post

get請求,因為查詢api可以看到有個postUrl方法。查看源碼可以確定

❺ android webview中的loadUrl方法是get請求還是post請求

我寫過的一般是get請求 因為一般這個loadUrl就是請求的完整地址 如果其實也很容易看 ,請求的時候介面端給你的介面是拼接了參數 的是get 請求 如果沒有拼接參數的話 可以是get也可以是post 這個咨詢下你們的寫介面的那個人也可以的 ,

❻ android loadjs是同步還是非同步

是同步載入的。

❼ android在用System.load()載入so文件時出現已經載入到內存錯誤,如何解決

這要看你在c++代碼里有沒有沒釋放的內存了。畢竟能成功運行一次,說明編譯沒錯誤,配置也沒錯誤。看檢察一下你的c++代碼。

❽ Android類載入機制

Android手寫熱修復(一)--ClassLoader

我們平時編寫的 .java 文件不是可執行文件,需要先編譯成 .class 文件才可以被虛擬機執行。所謂類載入是指通過 類載入器 把class文件載入到虛擬機的內存空間,具體來說是方法區。類通常是按需載入,即第一次使用該類時才載入。

首先,Java與Android都是把類載入到虛擬機內存中,然後由虛擬機轉換成設備識別的機器碼。但是由於二者使用的虛擬機不同,所以在類載入方面也是有所區別的。Java的虛擬機是JVM,Android的虛擬機是dalvik/art(5.0以後虛擬機是art,是對dalvik的一種升級)。 Java虛擬機運行的是class文件,而Android 虛擬機運行的是dex文件。 dex其實是class文件的集合,是對class文件優化的產物,是為了避免出現重復的class。

從上面的講解中,我們已經知道我們平時寫的類是被 類載入器 載入盡虛擬機內存才能運行。下面就通過Framework源碼來為大家講解Android中最主要的5個類載入器。

在Activity做個簡單驗證:

結果:

可以看出系統類由BootClassLoader載入,apk中的類由PathClassLoader載入,PathClassLoader的父類載入器是BootClassLoader。如果暫時不能理解父類載入器是什麼,沒關系,後面講雙親委託機制的時候會理解的。

下面的源碼解析基於 Android SDK API28 ,這幾個類載入器(除了ClassLoader)沒辦法直接在AS上查看源碼,AS搜索到的是反編譯的class的內容,是不可信的,為大家推薦一個在線工具查看, 在線查看Android Framework源碼 。

用來載入本地文件系統上的文件或目錄,通常是用來載入apk中我們自己寫的類,而像 Activity.class 這種系統的類不是由它載入。注意:這里,並不像很多網上文章說的那樣只能載入apk,本地的其他目錄的文件也是可以的,這一點我會在後面驗證說明。

也是被用來載入 jar 、apk、dex,通常用來載入未安裝到應用中的文件。注意,它需要一個應用私有的可寫的目錄來存放優化後的dex文件。千萬不要選擇外部存儲路徑,因為這樣可能會導致你的應用遭到注入攻擊。

關於dex文件優化,可能很多人還是不理解,水平有限,我簡單解釋一下,

構造器參數解釋:

關於optimizedDirectory:
1、這是dex優化後的路徑,它必須是一個應用私有的可寫的目錄否則會存在注入攻擊的風險;
2、這個參數在API 26(8.0)之前是有值的,之後的話,這個參數已經沒有影響了,因為在調用父構造器的時候這個參數始終為null,也就是說Android 8.0 以後DexClassLoader和PathClassLoader基本一樣的來;
3、在載入app的時候,apk內部的dex已經執行過優化了,優化之後放在系統目錄/data/dalvik-cache下。

這個構造器的關鍵是初始化了一個DexPathList對象,這個是後面載入class的關鍵類。

這個構造方法等關鍵是通過 makeDexElements() 方法來獲取Element數組,這個Element數組非常關鍵,後面查找class就會用到它,也是熱修復的關鍵點之一。

splitDexPath(dexPath) 方法是把dexPath目錄下的所有文件轉換成一個File集合,如果是多個文件的話,會用 : 作為分隔符。

makeDexElements()

小結一下,這個方法就是把指定目錄下的文件apk/jar/zip/dex按不同的方式封裝成Element對象,然後按順序添加到Element[]數組中。

DexPathList#loadDexFile()

可以看到 DexFile 最終是調用了openDexFile、native方法openDexFileNative去打開Dex文件的,如果outputName為空,則自動生成一個緩存目錄,具體來說是 /data/dalvik-cache/[email protected] 。openDexFileNative這個native方法就不具體分析了,主要是對dex文件進行了優化操作,將優化後得odex文件通過mmap映射到內存中。感興趣的同學可以參考:
《DexClassLoader和PathClassLoader載入Dex流程》

現在在回頭看看DexClassLoader與PathClassLoader的區別。DexClassLoader可以指定odex的路徑,而PathClassLoader則採用系統默認的緩存路徑,在8.0以後沒有區別。

ClassLoader是一個抽象類,有3個構造方法,最終調用的還是第一個構造方法,主要功能是保存實現類傳入的parent參數,也就是父類載入器。ClassLoader的實現類主要有2個,一個是前面講過的BaseDexClassLoader,另一個是BootClassLoader。

BootClassLoader是ClassLoader的內部類,而且繼承了ClassLoader。

這是載入一個類的入口,流程如下:
1、 先檢查這個類是否已經被載入,有的話直接返回Class對象;
2、如果沒有載入過,通過父類載入器去載入,可以看出parent是通過遞歸的方式去載入class的;
3、如果所有的父類載入器都沒有載入過,就由當前的類載入器去載入。

通常我們自己寫的類是通過當前類載入器調用 findClass 方法去載入的,但是在 ClassLoader 中這是個空方法,具體的實現在它的子類 BaseDexClassLoader 中。

BaseDexClassLoader # findClass

可以看到是通過pathList去查找class的,這個對象其實之前講過,它是在BaseDexClassLoader 的構造方法中初始化的,它實際上是一個 DexPathList 對象。

DexPathList # findClass()

對Element數組遍歷,再通過Element對象的 findClass 方法去查找class,有的話就直接返回這個class,找不到則返回null。 這里可以看出獲取Class是通過DexFile來實現的,而各種類載入器操作的是Dex。Android虛擬機載入的dex文件,而不是class文件。

1、載入一個類是通過雙親委託機制來實現的。
2、如果是第一次載入class,那是通過 BaseDexClassLoader 中的findClass方法實現的;接著進入 DexPathList 中的findClass方法,內部通過遍歷Element數組,從Element對象中去查找類;Element實際上是對Dex文件的包裝,最終還是從dexfile去查找的class。
3、一般app運行主要用到2個類載入器,一個是PathClassLoader:主要用於載入自己寫的類;另一個是BootClassLoader:用於載入Framework中的類;
4、熱修復和插件化一般是利用DexClassLoader來實現。
5、PathClassLoader和DexClassLoader其實都可以載入apk/jar/dex,區別是 DexClassLoader 可以指定 optimizedDirectory ,也就是 dex2oat 的產物 .odex 存放的位置,而 PathClassLoader 只能使用系統默認位置。但是在8.0 以後二者是沒有區別的,只能使用系統默認的位置了。

這張圖來源於:
Android虛擬機框架:類載入機制

在類載入流程分析中,我們已經知道,查找class是通過DexPathList來完成的,實際上DexPathList最終還是遍歷其Element數組,獲取DexFile對象來載入Class文件。 由於數組是有序的,如果2個dex文件中存在相同類名的class,那麼類載入器就只會載入數組前面的dex中的class。如果apk中出現了有bug的class,那隻要把修復的class打包成dex文件並且放在 DexPathList 中Element數組`的前面,就可以實現bug修復了 。下一篇為大家帶來的手寫熱修復。

Android類載入機制的細枝末節
從JVM到Dalivk再到ART(class,dex,odex,vdex,ELF)
類載入機制系列2——深入理解Android中的類載入器
Android 熱修復核心原理,ClassLoader類載入

熱點內容
sql語句on 發布:2025-02-05 07:41:42 瀏覽:596
取消電腦密碼怎麼設置8 發布:2025-02-05 07:24:16 瀏覽:393
洗腦編程 發布:2025-02-05 07:23:52 瀏覽:948
osd加密 發布:2025-02-05 07:17:39 瀏覽:36
微信游戲源碼下載 發布:2025-02-05 07:17:29 瀏覽:384
計算機內存儲器是 發布:2025-02-05 07:13:35 瀏覽:144
classpathlinux 發布:2025-02-05 07:12:57 瀏覽:564
linuxftp連接失敗 發布:2025-02-05 07:01:40 瀏覽:705
學生信息管理系統java 發布:2025-02-05 06:58:45 瀏覽:576
刺客信條4解壓後 發布:2025-02-05 06:55:23 瀏覽:901