Ubuntu虛擬機編譯Android6.0總結


1 前言

   昨天使用清華的源下載了android 6.0的源碼,校園網可以達到10M的速度,爽!今天一大早就迫不及待地准備編譯一個模擬器版本,看看效果,哪知竟然耗費了一整天的時間才搞定...為了避免其他人在同樣的問題上浪費時間,特記錄整個編譯過程中遇到的問題和解決方案,畢竟時間就是金錢!

2 背景

   我是在MAC上安裝的ubuntu14.04 64bit系統,起初分配了3G的內存(血的教訓,完全不夠用!),和兩個核心。編譯的系統版本為6.0.1_r9和6.0.0_r26

3 編譯過程遇到的問題和解決方案

   整個編譯過程嚴格按照官網的說明進行,不過因為不需要經常編譯源碼,同時為了節省空間,所以沒有使用ccache.

   起初編譯很順利,但是當執行到編譯java代碼(jar或者dex)階段的時候出現如下錯誤:

   

                                               圖3.1 編譯錯誤反饋信息 

   顯然,是一個叫做Jack的服務沒能啟動,那么這個Jack是干什么的呢?截取官網信息簡要概括如下:

   Jack (Java Android Compiler Kit)是一個新的Android編譯工具,用於將Java代碼編譯為Android dex字節碼,主要用於替換之前的編譯工具: javac, ProGuard, jarjar以及dx等等。更詳細的信息可參考官網介紹:

  https://source.android.com/source/jack.html#jack_intermediate_library_linker_jill

  Jack的重要性不言而喻,因此如果不能正常啟動它的話,我們的源碼是斷然無法編譯下去的。那么它為什么無法啟動呢?  

  查看官網,有如下兩條提示信息:

If your computer becomes unresponsive during compilation or if you experience Jack compilations failing on “Out of memory error”

You can improve the situation by reducing the number of Jack simultaneous compilations by editing your $HOME/.jack and changing SERVER_NB_COMPILE to a lower value. If your compilations are failing on “Cannot launch background server” The most likely cause is TCP ports are already used on your computer. Try to change it by editing your $HOME/.jack (SERVER_PORT_SERVICE and SERVER_PORT_ADMIN variables).

   排除第二種情況后,覺得第一種情況很有可能,因為從jack的啟動參數來看的話(從圖3.1編譯錯誤反饋信息可以看出),在啟動jack的時候為java虛擬機分配了2560M的內存,但我整個ubuntu虛擬機才3G啊!所以我馬上將Ubuntu虛擬機的內存增加到4G,然后重新編譯,不過我並沒有make clean因為前面非java部分的編譯都是沒問題的,而java部分編譯一開始就出錯了,所以不需要進行徹底地重新編譯。

   哪知,悲劇再次上演!當時兩眼抓瞎,都准備放棄了....中途去請教了下之前有過成功編譯經驗的同學,以為是版本的問題,所以將6.0.1_r9切換到6.0.0_r26后完全重新編譯,漫長等待后也是出現同樣的問題。這里記錄下切換源碼版本的方法:

① 首先進入源碼根目錄,將.repo/ 文件全部刪掉。
② 查看可切換的分支
    cd .repo/manifests
    git branch -a | cut -d / -f 3
    這里選擇6.0.0_r26即可
③ 切換分支
    repo init -b android-6.0.0.0_r26
④ 同步分支
   repo sync   
   注:因為我之前同步的是6.0.1_r9的源碼,所以這一步很快就完成了,根據git的原理,並不需要重新下載整個源碼,所以這里很快就完成了。

   

  顯然,這根系統版本並沒太大關系,繼續分析Jack無法啟動的原因。偶然發現每次編譯失敗之后都會在源碼根目錄生成如下日志文件:

   

   從名字就可以看出是一些錯誤日志,打開看一看,關鍵信息截取如下:

 1 #
 2 # There is insufficient memory for the Java Runtime Environment to continue.
 3 # Native memory allocation (malloc) failed to allocate 1789919232 bytes for committing reserved memory.
 4 # Possible reasons:
 5 #   The system is out of physical RAM or swap space
 6 #   In 32 bit mode, the process size limit was hit
 7 # Possible solutions:  8 # Reduce memory load on the system 9 # Increase physical memory or swap space 10 # Check if swap backing store is full 11 #   Use 64 bit Java on a 64 bit OS
12 #   Decrease Java heap size (-Xmx/-Xms)
13 #   Decrease number of Java threads
14 #   Decrease Java thread stack sizes (-Xss)
15 #   Set larger code cache with -XX:ReservedCodeCacheSize=
16 # This output file may be truncated or incomplete.
17 #
18 #  Out of Memory Error (os_linux.cpp:2827), pid=101129, tid=47875161523968
19 #
20 # JRE version:  (7.0_91-b02) (build )
21 # Java VM: OpenJDK 64-Bit Server VM (24.91-b01 mixed mode linux-amd64 compressed oops)
22 # Derivative: IcedTea 2.6.3
23 # Distribution: Ubuntu 14.04 LTS, package 7u91-2.6.3-0ubuntu0.14.04.1
24 # Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
25 #

     從紅色加粗的信息可以得到如下結論:在為Java虛擬機分配內存的時候失敗了,原因就是內存不夠用。但按照我的經驗來看的話,4G內存無論怎樣都夠用了,那為什么還是報錯呢?再仔細觀察一下錯誤日志,里面還提及了“swap空間問題”。問題可能出在它身上!swap分區主要用於在物理內存不夠用的情況下,使用硬盤來模擬擴展物理內存,只是速度要慢幾個數量級而已。

    我不記得當初安裝系統的時候是否分配了swap分區,所以使用如下命令查看:

chouchou:~$ sudo swapon -s
[sudo] password for chouchou:
Filename                Type        Size    Used    Priority

    信息竟然為空!也就是說我並沒有swap分區,下面就開始創建分區了,這里為了方便可以使用swap文件的方式來實現:

創建4G大小的swapfile
sudo fallocate -l 4G /swapfile 
設置/swapfile權限
sudo chmod 600 /swapfile
設置swapfile
sudo mkswap /swapfile
啟用
sudo swapon /swapfile
查看
 sudo swapon -s
[sudo] password for chouchou: 
Filename                Type        Size    Used    Priority
/swapfile                               file        4194300    345156    -1

   注意:這種方式創建的swap分區只是當前登錄狀態有效,重啟后就無效了。至於如何實現永久有效,大家可自行google。

   現在再次編譯,一次性通過!上圖:

   

4 總結

   這次編譯源碼花了一整天的時間,除了遇到Jack錯誤之外,在虛擬機里面編譯源碼效率低下也是一個重要的因素。因為隨着Android系統的升級,源碼越來越龐大,其所需要的編譯環境也跟着水漲船高,因此有條件的最好還是使用實體機編譯,且內存一定得大於4G!另外,遇到問題,第一時間查看錯誤日志也很關鍵,這樣往往能在搜索不到解決方案的時候,快速定位問題,節約很多時間!

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM