android下java的靜態庫和動態庫

very_on發表於2018-03-26
程式編制一般需經編輯、編譯、連結、載入和執行幾個步驟。在我們的應用中,有一些公共程式碼是需要反覆使用,就把這些程式碼編譯為“庫”檔案;在接步驟中,聯結器將從庫檔案取得所需的程式碼,複製到生成的可執行檔案中。這種庫稱為靜態庫,其特點是可執行檔案中包含了庫程式碼的一份完整拷貝;缺點就是被多次使用就會有多份冗餘拷貝。 

為了克服這個缺點可以採用動態接庫。這個時候接器僅僅是在可執行檔案中打上標誌,說明需要使用哪些動態連線庫;當執行程式時,載入器根據這些標誌把所需的動態接庫載入到記憶體。 

另外在當前的程式設計環境中,一般都提供方法讓程式在執行的時候把某個特定的動態連線庫載入並執行,也可以將其解除安裝(例如Win32的LoadLibrary()&FreeLibrary()和Posix的dlopen()&dlclose())。這個功能被廣泛地用於在程式執行時刻更新某些功能模組或者是程式外觀。 

與普通程式不同的是,Java程式(class檔案)並不是本地的可執行程式。當執行Java程式時,首先執行JVM(Java虛擬機器),然後再把Java class載入到JVM裡頭執行,負責載入Java class的這部分就叫做Class Loader。通常class檔案僅在需要使用時才載入。 這本身就是一種動態連結。

Java作為一種天生的動態連結語言,無法支援靜態連結。但C語言的靜態庫除了靜態連結的概念外,還隱含了一層意思,即庫中的程式碼會打包到可執行檔案中。JAVA中的JAR某種程度上類似一個可執行檔案或庫,借用C語言中靜態庫和動態庫的概念,這裡把最終會合併到生成的JAR檔案中的JAR包叫靜態庫,反之僅僅在編譯中使用,並不打包到生成的JAR包中,執行時需系統自行提供的JAR包叫動態庫。

C的靜態連結只把需要的程式碼複製過來,而Java用類似Fat Jar的方法,把所有的依賴庫打包到最後的庫中,眉毛鬍子一把抓。這個問題可以用ProGuard解決,用它自己的話說是 It detects and removes unused classes, fields, methods, and attributes。

Eclipse中對JAR包的使用方式有兩種,library和user libraries,其中library在工程中通過add jars...或add external jars...新增,出現在Referenced Libraries中,而user libraries需要在工作空間中管理,再在工程中通過add library...新增。這兩種使用方式本身並沒有靜態庫和動態庫的區別,需要在打包或部署時再行指定。但user libraries的方式明顯更方便管理多個工程共同使用的多個庫,而系統庫往往都有這種特性。

android的apk比JAR更類似可執行程式,而且因為標準庫隱藏了很多功能,我們常常需要使用自己構建的系統庫來編譯。但android的ADT工具並沒有提供是否將library或user libraries打包的選項。根據我的經驗,ADT預設將library打包到apk中,而user libraries則僅用於編譯,執行時再請求系統載入相關類。哪位同學有更明確的資訊,還望指教,我短期內恐怕不會有時間去研究這個問題。

因此,可以這麼說,在android中,library用來新增靜態庫,而user libraries用來管理動態庫。千萬不能弄錯了,如果把靜態庫錯誤地加入動態庫,執行時會出現找不到對應的class的錯誤,但因為Java語言的動態連結機制,只有執行到庫中程式碼時才會出錯;反之,如果把動態庫做成了靜態庫,問題就更隱蔽了,可能只是dex檔案特別大,而沒有其它問題,也可能因載入了錯誤版本的系統程式碼,出現一些稀奇古怪的問題。慎之,慎之...

附:向eclispe中新增user Libraries的步驟: 
1。點選eclipse的window選單,選擇“Preference” 
2。在preferences視窗中選擇java->User Libraries,然後點選視窗右邊的New...按鈕,在彈出的子視窗中輸入user library的名稱,此時在user libraries視窗中會出現新加的library名稱。 
3。向該user library中新增jar包。選中my_lib,然後點選Add JARS...按鈕,選擇你要新增的jar後,點選“開啟”按鈕,則my_lib庫中就會出現你剛新增的jar檔案資訊。 
4。最後點選視窗下的“OK”按鈕,完成user library的新增和其jar的新增。

相關文章