Ubuntu虚拟机编译Android6.0总结

1 前言html

   昨天使用清华的源下载了android 6.0的源码,校园网能够达到10M的速度,爽!今天一大早就火烧眉毛地准备编译一个模拟器版本,看看效果,哪知居然耗费了一成天的时间才搞定...为了不其余人在一样的问题上浪费时间,特记录整个编译过程当中遇到的问题和解决方案,毕竟时间就是金钱!java

2 背景linux

   我是在MAC上安装的ubuntu14.04 64bit系统,起初分配了3G的内存(血的教训,彻底不够用!),和两个核心。编译的系统版本为6.0.1_r9和6.0.0_r26android

3 编译过程遇到的问题和解决方案git

   整个编译过程严格按照官网的说明进行,不过由于不须要常常编译源码,同时为了节省空间,因此没有使用ccache.ubuntu

   起初编译很顺利,可是当执行到编译java代码(jar或者dex)阶段的时候出现以下错误:工具

   

                                               图3.1 编译错误反馈信息 oop

   显然,是一个叫作Jack的服务没能启动,那么这个Jack是干什么的呢?截取官网信息简要归纳以下:ui

   Jack (Java Android Compiler Kit)是一个新的Android编译工具,用于将Java代码编译为Android dex字节码,主要用于替换以前的编译工具: javac, ProGuard, jarjar以及dx等等。更详细的信息可参考官网介绍:google

  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!另外,遇到问题,第一时间查看错误日志也很关键,这样每每能在搜索不到解决方案的时候,快速定位问题,节约不少时间!

相关文章
相关标签/搜索