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

时间: 2024-12-24 11:53:44

Ubuntu虚拟机编译Android6.0总结的相关文章

在Ubuntu Server14.04上编译Android6.0源码

此前编译过Android4.4的源码,但是现在Android都到了7.0的版本,不禁让我感叹Google的步伐真心难跟上,趁这周周末时间比较充裕,于是在过去的24小时里,毅然花了9个小时编译了一把Android6.0的源码,但是昨天编译完之后已经很晚了,没来得及记录编译的步骤,今天才慢悠悠地来记录一下我在Ubuntu Server14.04上编译Android6.0源码的步骤.好了,废话不多说,我们开始吧! 步骤一: 安装Ubuntu系统.我们既可以通过虚拟机的方式安装Ubuntu,也可以直接在

Ubuntu下编译3.0.4内核

Ubuntu下编译3.0.4内核 Linux内核3.0版本发布已有一段时间了,不知道这个版本号大跃进的内核是否好用.目前各个发行版的linux还仍未采用3.0的内核,因此可以自己动手编译内核来感受一下!趁着这次编译内核的机会可以再熟悉一下编译内核的步骤. 1.下载并解压内核到任意目录 从源码官网下载最新的内核源码3.0.4,可以解压至任意目录,我放在主目录下: 1 ~$ tar xjvf linux-3.0.4.tar.bz2 2.配置内核 对内核进行配置是为了得到内核配置文件.config.通

Ubuntu16.04下编译android6.0源码

http://blog.csdn.net/cnliwy/article/details/52189349 作为一名合格的android开发人员,怎么能不会编译android源码呢!一定要来一次说编译就编译的旅程,否则你的人生是不完整的!好,那么我们进入正题! 本次编译环境采用Ubuntu16.04LTE,android源码选择android6.0!官方建议采用Ubuntu14版本,主要是我刚开始没在意系统版本,然后就直接下载安装16.04版本了,然后也懒得换了,所以就选择了这个版本....下面我

Ubuntu 下载编译 Android5.0 源码

1.安装ubuntu 编译Android 5.0 需要ubuntu 64位的操作系统,在 http://mirrors.ustc.edu.cn/ubuntu-releases/14.10/ 下载Ubuntu 14.10 64 位版本. 提示: 1.建议下载14.10,不要下载14.04,在安装编译需要的软件时,各种依赖问题,很难麻烦 2.ubuntu 的磁盘空间需要给大一点,在创建虚拟机的时候,第一次改50g编译一半提示磁盘空间不够,给到100g就差不多了 2.安装openjdk-7-jdk A

Ubuntu 下载 & 编译 Android5.0 源码

 1.安装openjdk-7-jdk Android 5.0 用到的jdk不再是Oracle 的 jdk ,而是开源的 openjdk,在ubuntu安装好后,使用如下命令安装jdk: $sudo apt-get install openjdk-7-jdk 安装好后,设置环境变量: 在/etc/profile 文件末尾加上: JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/ PATH=$PATH:$HOME/bin:$JAVA_HOME/bin expor

Ubuntu16.04编译Android6.0/cm13.0教程及相关错误解决办法

一.必备工作 1.安装依赖库 sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib git flex bison gperf build-essential libncurses5-dev:i386 tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386 dpkg-dev libsdl1.2-dev li

ubuntu12.04下编译 全志A33 android6.0 源码

有错误请指出. 入职4天了,为了编译android6.0搞的很烦,遇到了很多问题,会将我遇到的问题写出来,做个总结. 我用的是ubuntu12.04,16.04应该也是可行的. 编译时遇到的问题大部分是缺少包的问题,编译之前首先 我装完ubuntu自带了openjdk7,但是之前读开发手册需要jdk1.6,先去下载jdk-6-linux-64.bin安装过后,配置环境变量,配置环境变量后 执行以下命令,单单是编译,这里有很多都不需要,不过为了以防万一 $sudo apt-get install

《linux 内核完全剖析》编译linux 0.12 内核 Ubuntu 64bits 环境

我×...终于好了,大概3 4个小时吧...各种毛刺问题.终究还是闯过来了.... [email protected]:~/Downloads/linux-0.00-050613/linux-0.00$ make ld -s -x -M head.o  -o system > System.map dd bs=32 if=boot of=Image skip=1 16+0 records in 16+0 records out 512 bytes (512 B) copied, 0.000605

Android5.1和Android6.0定时编译项目方法 (转)

为了不占用开发的时间,我们通常会选择晚上下班后让项目自动编译,那么如何定时编译项目呢.Android5.1和Android6.0定时编译项目的方法是一样的,下面就我本地的C100H_V20(Android5.1)项目工程为例: 首先总体看一下工程下面都有那些文件: 然后打开你的编译脚本,里面的内容如下: [java] view plain copy #update svn cleanup svn up #compile chmod 777 -R ./ source build/envsetup.