真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

androidso加載,android動態(tài)加載so文件

安卓JVM加載so庫流程

好久沒有寫點(diǎn)東西發(fā)了,工作中的事情有點(diǎn)雜,也找不到整塊東西可以寫的。

創(chuàng)新互聯(lián)是一家專注于做網(wǎng)站、成都網(wǎng)站制作與策劃設(shè)計,扎蘭屯網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:扎蘭屯等地區(qū)。扎蘭屯做網(wǎng)站價格咨詢:18982081108

最近調(diào)查了一個問題,稍微追了一下流程,這里記錄一下。

由于我們支持的設(shè)備相對比競品,zygote進(jìn)程多占用了好幾倍的內(nèi)存空間。通過dump meminfo后發(fā)現(xiàn),我們的設(shè)備在so庫,ttf,和unkonwn mmap的內(nèi)存空間相比競品一共大了20多M,其中so庫多了15M左右。

通過查看zygote進(jìn)程的smaps,確定了占用空間最大的幾個so庫確實(shí)是我們自己的。雖然確定了內(nèi)存占用大的原因,還是得把這些so庫是加載在zygote進(jìn)程中的時機(jī)確定了才行。

我的第一反應(yīng)就是在zygote啟動時,加載sharedLibrary()時,把這些庫加載了,于是去看了這部分源碼,并沒有。

通過反復(fù)調(diào)試以及追蹤源碼,最后發(fā)現(xiàn)是在JVM啟動的過程中加載了這些so庫,這些so庫的配置在“system/etc/public.libraries.txt”下。

這個文件里配置的都是public的so庫,能夠被普通app訪問的。類似的配置文件還有“vendor/etc/”下面的,還有一些其他的配置地方,我沒有深入去看,想要看的盆友可以自己去看源碼或者注釋。

下面我就帶大家一起看看虛擬機(jī)加載這些so庫的流程。

調(diào)用棧:

frameworks/base/cmds/app_process/app_main.cpp

----runtime.start("com.android.internal.os.ZygoteInit", args, zygote);

frameworks/base/core/jni/AndroidRuntime.cpp

----AndroidRuntime::startVm

---JNI_CreateJavaVM(pJavaVM, pEnv, initArgs)

art/runtime/jni/java_vm_ext.cc

---android::InitializeNativeLoader();

system/core/libnativeloader/native_loader.cpp

----Initialize()

----ReadConfig(public_native_libraries_system_config, sonames, always_true, error_msg)

其中,public_native_libraries_system_config 為 system/etc/public.libraries.txt

這部分流程是在安卓設(shè)備開機(jī)過程中的,在執(zhí)行ZygoteInit.main()之前會先啟動java虛擬機(jī)的,這樣fork其他java進(jìn)程的時候,java環(huán)境就已經(jīng)有了,不用再創(chuàng)建虛擬機(jī)了。

最后貼一下Initialize()函數(shù):

android項目中如何加載已有so庫

1,在項目根目錄下建立文件夾libs/armeabi文件夾

2,將so庫放入libs/armeabi文件夾注意事項:

1,如果采用靜態(tài)注冊的方式請注意C文件中嚴(yán)格按照命名規(guī)則Java_packageName_className_method()的方式命名

2,在Android項目中建立同上述命名規(guī)則中packageName中相同的包名,在此包名下建立同上述命名規(guī)則中className相同的類名

3,在className聲明native方法

4,程序中加載so庫System.loadLibrary(data/data/xxx.xxx.xxx/lib/xx.so)或者System.loadLibrary(xx),例如:System.loadLibrary(data/data/com.dtBank.app.service/lib/libjnixcld.so);

Android 應(yīng)用push ,so無法加載

作者君主要做SDK開發(fā),對接一些廠商或運(yùn)行商的普通應(yīng)用或系統(tǒng)應(yīng)用。

當(dāng)對接系統(tǒng)應(yīng)用時,由于系統(tǒng)應(yīng)用是由于覆蓋機(jī)型比較廣,會碰到Android多個版本機(jī)型,有的可能出現(xiàn)so找不到的問題。

普通install安裝apk的方式,apk會被安裝在 /data/app 目錄下,那么So則會被映射到/data/app/項目目錄下/lib。

首次安裝只能通過直接push到/system/app/下的方式來安裝,而不是如普通應(yīng)用般采取install的方式。

android在開機(jī)掃描應(yīng)用的時候會對 相應(yīng)目錄進(jìn)行掃描,如果發(fā)現(xiàn) data/app目錄下 存在和系統(tǒng)應(yīng)用同包名的應(yīng)用,并且版本號比系統(tǒng)應(yīng)用的版本號更高則構(gòu)成升級關(guān)系,校驗(yàn)簽名等安全驗(yàn)證通過。此時data/app下的這個應(yīng)用就是系統(tǒng)應(yīng)用

而push到系統(tǒng)目錄下如system/app/....,則會優(yōu)先尋找system/lib(lib64)目錄下的so,由于so

不會自動釋放到該目錄下,所以需要手動push到該路徑下。

作者君還遇到過這樣的問題,有時候?yàn)榱藴p少包的大小或者其他,不會把所有ABI類型的so都放進(jìn)目錄,另外so的提供者團(tuán)隊沒有提供64的so(哈哈,如果提供了,下面的問題直接就沒有了,那為什么還拿出來說呢,主要是簡單地了解一下系統(tǒng)底層的一些基本原理,感興趣的可以看下一下~~)

機(jī)型類型是64位的,其他apk僅提供了64位的so。而某個apk由于只集成了32位so, install安裝是正常的,但是把a(bǔ)pk通過push到/system/app下,so放到/system/lib下則報如下錯誤:

32位機(jī)器上當(dāng)然是正常的。

那么為什么會出錯呢?首先是系統(tǒng)級應(yīng)用,需要理解Android系統(tǒng)的原理(當(dāng)然啦,也許廠商定制了一番,那則另一回事。):

系統(tǒng)有幾個屬性,其中app.info.primaryCpuAbi這個值用來決定apk關(guān)聯(lián)ABI類型。而PackageManager會對這個值有所影響。比如:通過apk包里包含的so庫的架構(gòu)來決定app的primaryCpuAbi的值。

另外:

如果機(jī)器里有64位的apk,且PackageManager掃描到第一正好是這個apk,PackageManager調(diào)整所有apk要加載的都是64位的so。不再去加載32位的so,那么只含32位so的apk就會跑出異常。反之,則64位的apk正常運(yùn)行,32位的則出錯。

作者君能力有限,如有錯處,請書友們指導(dǎo),作者君會第一時間修改。

一起學(xué)習(xí) 一起進(jìn)步 ?( ′???` )比心

Android studio 怎么加載.so文件

1、在src/main中添加

jniLibs文件夾

,把.so復(fù)制進(jìn)去

2、在build.gradle中就添加這么幾行

,

看圖

復(fù)制內(nèi)容到剪貼板

sourceSets

{

main

{

jniLibs.srcDirs

=

['libs']

}

}

3、然后make

project

4、切換到android結(jié)構(gòu)下,你會看到

jniLibs

中.so已經(jīng)變成了.jar文件,證明已經(jīng)成功

如何加載so文件 android

android中加載so文件:

在Android中調(diào)用動態(tài)庫文件(*.so)都是通過jni的方式,而且往往在apk或jar包中調(diào)用so文件時,都要將對應(yīng)so文件打包進(jìn)apk或jar包,工程目錄下圖:

Android中加載so文件的提供的API:

void System.load(String pathName);

說明:

1、pathName:文件名+文件路勁;

2、該方法調(diào)用成功后so文件中的導(dǎo)出函數(shù)都將插入的系統(tǒng)提供的一個映射表(類型Map);

3、具體代碼如下:

try {?

String localPath = Environment.getExternalStorageDirectory() + path;?

Log.v(TAG, "LazyBandingLib localPath:" + localPath);

String[] tokens = mPatterns.split(path);?

if (null == tokens || tokens.length = 0?

|| tokens[tokens.length - 1] == "") {?

Log.v(TAG, "非法的文件路徑!");?

return -3;?

}?

// 開辟一個輸入流?

File inFile = new File(localPath);?

// 判斷需加載的文件是否存在?

if (!inFile.exists()) {?

// 下載遠(yuǎn)程驅(qū)動文件?

Log.v(TAG, inFile.getAbsolutePath() + " is not fond!");?

return 1;?

}?

FileInputStream fis = new FileInputStream(inFile);

File dir = context.getDir("libs", Context.MODE_PRIVATE);?

// 獲取驅(qū)動文件輸出流?

File soFile = new File(dir, tokens[tokens.length - 1]);?

if (!soFile.exists()) {?

Log.v(TAG, "### " + soFile.getAbsolutePath() + " is not exists");?

FileOutputStream fos = new FileOutputStream(soFile);?

Log.v(TAG, "FileOutputStream:" + fos.toString() + ",tokens:"?

+ tokens[tokens.length - 1]);

// 字節(jié)數(shù)組輸出流,寫入到內(nèi)存中(ram)?

ByteArrayOutputStream baos = new ByteArrayOutputStream();?

byte[] buffer = new byte[1024];?

int len = -1;?

while ((len = fis.read(buffer)) != -1) {?

baos.write(buffer, 0, len);?

}?

// 從內(nèi)存到寫入到具體文件?

fos.write(baos.toByteArray());?

// 關(guān)閉文件流?

baos.close();?

fos.close();?

}?

fis.close();?

Log.v(TAG, "### System.load start");?

// 加載外設(shè)驅(qū)動?

System.load(soFile.getAbsolutePath());?

Log.v(TAG, "### System.load End");

return 0;

} catch (Exception e) {?

Log.v(TAG, "Exception?? " + e.getMessage());?

e.printStackTrace();?

return -1;

}

Android So加載的路徑選擇

我們在Android應(yīng)用程序會常常的加載一些So文件來完成我們的目標(biāo),那么我們的APK加載So是有哪些平時我們沒有注意到的事情呢?

1. 首先我們一般開發(fā)會遇見兩種APK(其實(shí)一般大部分只會遇到一種),一種為系統(tǒng)級APK,另外一種為普通APK。那么這個兩種APK跟So加載有什么關(guān)系呢?別急,讓我們先聊聊我們那些操作會產(chǎn)生這些類型的APK。

普通級AKP:?

pm install +?包名將會把APK安裝到 /data/app 目錄下,同時會把So映射到/data/app-lib/包命/ 目錄下。這個就是普通的APK(pm Install -r 會替換原有的APK,當(dāng)然必須是一樣的簽名)。

系統(tǒng)級APK:

push? + 絕對路徑 + 包名 /system/app 目錄下(必須把原有的包名刪除哦!),這時APK就會在System/app下面了,這時你需要把你的APK的So 同時push到system/lib里面。因?yàn)閍pk里面的So并不會自動映射到system/lib下面。

一般我們在使用加載So的方法時候,會使用到System.load(pathName)和?System.loadLibrary(libName)這兩種方法。這篇文章主要講講System.load(pathName)這個絕對路徑加載的注意點(diǎn)。

我們通常會直接使用

context.getApplicationInfo().nativeLibraryDir +/具體名字.so? 來讓系統(tǒng)幫我尋找加載So所需要的路徑。那么這里問題就來了。

如果是系統(tǒng)級APK

context.getApplicationInfo().nativeLibraryDir = /system/lib/

如果是普通級APK

context.getApplicationInfo().nativeLibraryDir ?=/data/data-lib/PackageName/ 對!就是那個映射的So系統(tǒng)會根據(jù)這個去data/app/包名下面尋找真正的So文件。

這個需要注意的細(xì)節(jié),主要用于在中間件,系統(tǒng)預(yù)置程序的研發(fā)人員與測試上面。我們在拿到芯片廠商給予調(diào)試模式的開發(fā)硬件上進(jìn)行Demo和So的更換測試的時候,需要自己和測試都需要知道,自己安裝的APK是什么類型,會加載什么路徑,以免我們的底層老司機(jī)在幫忙測試問題的時候造成不必要的麻煩。


文章名稱:androidso加載,android動態(tài)加載so文件
網(wǎng)站鏈接:http://weahome.cn/article/dsgdeoj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部