背景
需要在一个Android7平台上进行有关的工作,但是编译的时候发现有问题。记录一下。因为和同事共用一台服务器,因为他的编译没问题;而我的编译没成功。
在网上收集了各方的资料,再结合自己的经验,终于解决了这个问题。
介绍
Android7.0(也就是Android N)以上默认使用JACK编译器而不再使用openjdk了。
Android7.0系统编译工具链使用了全新的Jack server来取代以往的编译器工具
Jack is a new Android toolchain that compiles Java source into Android dex bytecode. It replaces the previous Android toolchain, which consists of multiple tools, such as javac, ProGuard, jarjar, and dx.
然而,在 2017 年 3 月 14 日公告发布之后,Jack 工具链已被弃用。Jack 是 Android 6.0–8.1 的默认 Android 编译工具链。
当你编译Android时,只需使用标准的makefile命令执行即可。当第一次执行编译时,会在你的机器上启动一个jack编译服务: 这个服务大大提高了编译速度,因为它避免了启动一个新的JVM,加载Jack代码,初始化Jack和每次编译都要预制JIT,即使在很小的编译过程中,它也很好的节省了时间。
这个服务也是一个控制Jack并行编译的短期解决方案。它可以限制编译的并行数据量,这样也可以避免内存硬盘溢出问题。
当一段时间没有编译活动,Jack 服务会自动关闭,默认它在本地使用了两个TCP端口,且不对外公开。它也提供了很多参数来配置Jack服务,例如并行数量,timeout时间,端口等等。
但是,如果不做修改时,同一台linux服务器上不允许不同用户同时进行andorid7.0的编译,体现为:第二个开始编译的用户无法正常启动jack server,且jack server居然不能关闭。
虽然JACK文档中有说提供一些宏,理论上只要设置宏为对应的值就可以关闭,但实测发现无效。
报错:Communication error with Jack server (58), try 'jack-diagnose' or see Jack server log
原因:JACK编译器不支持多用户同时编译,其他用户在编译,端口被占用。
解决方法
以下是我自己试过的做法。
修改$HOME/.jack-settings
和$HOME/.jack-server/config.properties
中的端口号,方可支持多用户同时编译。
注意事项:
0、编译成功的用户的配置才允许修改。(编译失败的用户修改会遇到很多问题)
1、两个文件中的端口号必须一致。
2、修改后的端口号必须是没有被使用的。
新用户删除目录
在编译失败的用户上,删除有关配置。
这样的做法是为了避免 直接修改
$HOME/.jack-settings
造成的种种问题。
sudo rm $HOME/.jack-settings $HOME/.jack-server/ -rf
旧用户修改配置
在编译成功的用户上,修改以下配置:
-
$HOME/.jack-settings
:
# Server settings
SERVER_HOST=127.0.0.1
SERVER_PORT_SERVICE=8776 # Port A
SERVER_PORT_ADMIN=8777 # Port B
# Internal, do not touch
SETTING_VERSION=4
-
$HOME/.jack-server/config.properties
:
#Fri Nov 02 14:18:58 CST 2018
jack.server.idle=180
jack.server.max-service.by-mem=1\=2147483648\:2\=3221225472\:3\=4294967296
jack.server.shutdown=21600
jack.server.time-out=7200
jack.server.max-jars-size=104857600
jack.server.service.port=8776 # Port A
jack.server.admin.port=8777 # Port B
jack.server.config.version=4
jack.server.max-service=4
jack.server.deep-idle=900
重启机器
为了方便,直接重启机器更好。
修改以后,重启服务。
out/host/linux-x86/bin/jack-admin kill-server
out/host/linux-x86/bin/jack-admin start-server
# 或者
./prebuilts/sdk/tools/jack-admin kill-server
./prebuilts/sdk/tools/jack-admin start-server
如果出现下列错误:
Launching Jack server java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=/tmp -Dfile.encoding=UTF-8 -XX:+TieredCompilation -cp /home/schips/.jack-server/launcher.jar com.android.jack.launcher.ServerLauncherJack server failed to (re)start, try 'jack-diagnose' or see Jack server log
No Jack server running. Try 'jack-admin start-server'
No Jack server running. Try 'jack-admin start-server'
可以使用./prebuilts/sdk/tools/jack-admin dump-report
将日志dump出来。
$ ./prebuilts/sdk/tools/jack-admin dump-report
Creating report...
Dumping Jack server stacks...
Getting current user id...
Listing Jack server process...
Listing process using Jack server service port 8776...
Listing process using Jack server admin port 8777...
Collecting Jack client configuration...
Listing Jack server installation dir...
Collecting curl version...
Collecting curl connection info...
Collecting Jack server stats...
Zipping Jack server installation dir except keys and certificates...
Jack server report saved in 'jack-report.254730.zip'. Consider reviewing content before publishing.
会得到 jack-report.xx.zip
,解压以后,再根据具体的原因对report.xxxxx.txt
进行排查:
错误原因 | 解决 |
Protocol https not supported or disabled in libcurl | 安装 |
connect to 127.0.0.1 port 8777 failed: Connection refused | 修改对应的文件权限, |
也可以根据文件 $HOME/.jack-server/logs/jack-server-0-*.log
:查看错误原因
10:26:40.898:SEVERE: com.android.jack.launcher.ServerLauncher: Server 1 Exception
com.android.jack.server.api.v01.ServerException: './config.properties' **musthave permission rw------- but have rwx------**
atcom.android.jack.server.JackServerImpl.run(JackServerImpl.java:65)
atcom.android.jack.launcher.ServerLauncher$3.run(ServerLauncher.java:391)
atjava.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: './config.properties' must have permission rw------- but have rwx------
at com.android.jack.server.JackHttpServer.checkAccess(JackHttpServer.java:696)
atcom.android.jack.server.JackHttpServer.loadConfig(JackHttpServer.java:513)
atcom.android.jack.server.JackHttpServer.<init>(JackHttpServer.java:379)
at com.android.jack.server.JackServerImpl.run(JackServerImpl.java:61)
... 2 more
发现是配置文件的权限不对造成的,把文件$HOME/.jack-server/config.properties
的权限由rwx改为rw即可解决问题。
chmod 600 $HOME/.jack-server/config.properties $HOME/.jack-settings
另外一个权限问题:那个目录不应该由root以外的其他用户持有。
com.android.jack.server.api.v01.ServerException: '.' is not owned by 'root' but by 'user'
at com.android.jack.server.JackServerImpl.run(JackServerImpl.java:65)
at com.android.jack.launcher.ServerLauncher$3.run(ServerLauncher.java:391)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: '.' is not owned by 'root' but by 'user'
at com.android.jack.server.JackHttpServer.getCurrentUser(JackHttpServer.java:1040)
at com.android.jack.server.JackHttpServer.<init>(JackHttpServer.java:377)
at com.android.jack.server.JackServerImpl.run(JackServerImpl.java:61)
... 2 more
解决方法:
sudo chown root $HOME/.jack-server/
sudo chgrp root $HOME/.jack-server/
重新编译
之前编译失败的用户,重新编译试试。如果成功,再如同编译成功的用户修改配置一样,再将自己的端口号改掉。
此后,如果有新的用户需要编译,以这个方法重试即可。
附录:网友的调试记录
尝试关闭JACK,但发现失败
1),当在板型目录中的BoardConfig.mk中添加ANDROID_COMPILE_WITH_JACK:=false时,编译会出错:
ninja: error: 'out/target/common/obj/APPS/ActSensorCalib_intermediates/with-local/classes.dex', needed by 'out/target/common/obj/APPS/ActSensorCalib_intermediates/classes.dex', missing and no known rule to make it
make[1]: *** [ninja_wrapper] Error 1
2),当在板型目录中的BoardConfig.mk中添加DEFAULT_JACK_ENABLED := disabled时,仍然不能关闭JACK,都会报错:
[ 34% 13188/37803] Ensure Jack server is installed and started
FAILED: /bin/bash -c "(prebuilts/sdk/tools/jack-admin install-server prebuilts/sdk/tools/jack-launcher.jar prebuilts/sdk/tools/jack-server-4.8.ALPHA.jar 2>&1 || (exit 0) ) &&
(JACK_SERVER_VM_ARGUMENTS=\"-Dfile.encoding=UTF-8 -XX:+TieredCompilation\" prebuilts/sdk/tools/jack-admin start-server 2>&1 || exit 0 ) &&
(prebuilts/sdk/tools/jack-admin update server prebuilts/sdk/tools/jack-server-4.8.ALPHA.jar 4.8.ALPHA 2>&1 || exit 0 ) &&
(prebuilts/sdk/tools/jack-admin update jackprebuilts/sdk/tools/jacks/jack-2.28.RELEASE.jar 2.28.RELEASE || exit 47;
prebuilts/sdk/tools/jack-admin update jack prebuilts/sdk/tools/jacks/jack-3.36.CANDIDATE.jar 3.36.CANDIDATE || exit 47;
prebuilts/sdk/tools/jack-admin update jack prebuilts/sdk/tools/jacks/jack-4.7.BETA.jar 4.7.BETA || exit 47 )"
Writing client settings in /home/test/.jack-settings
Installing jack server in "/home/test/.jack-server"
Communication error with Jack server (58), try 'jack-diagnose' or see Jack server log
Failed to contact Jack server: Problem reading /home/test/.jack-server/client.pem. Try 'jack-diagnose'
Failed to contact Jack server: Problem reading /home/test/.jack-server/client.pem. Try 'jack-diagnose'
[ 34% 13188/37803] Compiling SDK Stubs...tubs_current_intermediates/classes.jar
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
[ 34% 13188/37803] target SharedLib: l...bLLVM_intermediates/LINKED/libLLVM.so)
ninja: build stopped: subcommand failed.
make[1]: *** [ninja_wrapper] Error 1
make[1]: Leaving directory `/home/test/700E/android/android'
3),尝试通过设置ANDROID_FORCE_JACK_ENABLED := disabled来进行关闭JACK ,编译也报错,跟1)一样的错误:
ninja: warning: multiple rules generate out/target/product/s900_RY_VR/system/xbin/su. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn]
ninja: error: 'out/target/common/obj/APPS/ActSensorCalib_intermediates/with-local/classes.dex', needed by 'out/target/common/obj/APPS/ActSensorCalib_intermediates/classes.dex', missing and no known rule to make it
make[1]: *** [ninja_wrapper] Error 1
修改配置
网上有很多人反映这个问题,https://code.google.com/p/android/issues/detail?id=194027,但是目前没有有效的解决方案,最可能的办法是从2个方面尝试:
1),这个issue有人说是需要增加RAM:I was on VitualMachine when I had the error. And the fix was to increase the RAM,不过他是在虚拟机上,我们的应该跟RAM无关;
2),通过修改配置文件$HOME/.jack-settings,设置不同的端口号:
# Server settings
SERVER_HOST=127.0.0.1
SERVER_PORT_SERVICE=8076
SERVER_PORT_ADMIN=8077
# Internal, do not touch
SETTING_VERSION=4
通过实验发现,单独修改配置文件$HOME/.jack-settings中的端口号没有效果,jack server一直启动失败,提示端口被占用:
com.android.jack.server.api.v01.ServerException: Problem while opening service port
at com.android.jack.server.JackHttpServer.start(JackHttpServer.java:611)
at com.android.jack.server.JackServerImpl.run(JackServerImpl.java:62)
at com.android.jack.launcher.ServerLauncher$3.run(ServerLauncher.java:391)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.BindException: **Address already in use**
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:433)
at sun.nio.ch.Net.bind(Net.java:425)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
at com.android.jack.server.ServerParameters.openSocket(ServerParameters.java:88)
at com.android.jack.server.ServerParameters.getServiceSocket(ServerParameters.java:67)
at com.android.jack.server.JackHttpServer.start(JackHttpServer.java:605)
3),需要同时修改 $HOME/.jack-server/config.properties 中的端口号,方才有效,可以在别的用户启动了jack server的情况再启动另一个jack server,这样就可以实现多用户同时编译,亲测有效:
#Tue Sep 13 17:44:41 CST 2016
jack.server.max-jars-size=104857600
jack.server.max-service=4
jack.server.service.port=8076 # 修改这里
jack.server.max-service.by-mem=1\=2147483648\:2\=3221225472\:3\=4294967296
jack.server.admin.port=8077 # 修改这里
jack.server.config.version=2
jack.server.time-out=7200
总结一下解决方案就是:
同时修改$HOME/.jack-settings
和$HOME/.jack-server/config.properties
中的端口号,方可支持多用户同时编译。
补充一下后来编译遇到的错误的解决方法:
错误提示:
[ 8% 1/12] Ensure Jack server is installed and started
再试了一次还是报错:
FAILED:/bin/bash -c "(prebuilts/sdk/tools/jack-admin install-serverprebuilts/sdk/tools/jack-launcher.jar prebuilts/sdk/tools/jack-server-4.8.ALPHA.jar2>&1 || (exit 0) ) &&(JACK_SERVER_VM_ARGUMENTS=\"-Dfile.encoding=UTF-8-XX:+TieredCompilation\" prebuilts/sdk/tools/jack-admin start-server2>&1 || exit 0 ) && (prebuilts/sdk/tools/jack-admin updateserver prebuilts/sdk/tools/jack-server-4.8.ALPHA.jar 4.8.ALPHA 2>&1 ||exit 0 ) && (prebuilts/sdk/tools/jack-admin update jackprebuilts/sdk/tools/jacks/jack-2.28.RELEASE.jar 2.28.RELEASE || exit 47;prebuilts/sdk/tools/jack-admin update jackprebuilts/sdk/tools/jacks/jack-3.36.CANDIDATE.jar 3.36.CANDIDATE || exit 47;prebuilts/sdk/tools/jack-admin update jackprebuilts/sdk/tools/jacks/jack-4.7.BETA.jar 4.7.BETA || exit 47 )"
Jack server already installed in"/home/local/ACTIONS/songzhining/.jack-server"
Launching Jack server java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=/tmp-Dfile.encoding=UTF-8 -XX:+TieredCompilation -cp/home/local/ACTIONS/songzhining/.jack-server/launcher.jarcom.android.jack.launcher.ServerLauncher
Jack server failed to (re)start, try 'jack-diagnose' or see Jack server log
No Jack server running. Try 'jack-admin start-server'
No Jack server running. Try 'jack-admin start-server'
ninja: build stopped: subcommand failed.
make[1]: *** [ninja_wrapper] Error 1
解决方案:
通过查看文件 $HOME/.jack-server/logs/jack-server-0-0.log
:
10:26:40.898:SEVERE: com.android.jack.launcher.ServerLauncher: Server 1 Exception
com.android.jack.server.api.v01.ServerException: './config.properties' **musthave permission rw------- but have rwx------**
atcom.android.jack.server.JackServerImpl.run(JackServerImpl.java:65)
atcom.android.jack.launcher.ServerLauncher$3.run(ServerLauncher.java:391)
atjava.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: './config.properties' must have permission rw------- but have rwx------
at com.android.jack.server.JackHttpServer.checkAccess(JackHttpServer.java:696)
atcom.android.jack.server.JackHttpServer.loadConfig(JackHttpServer.java:513)
atcom.android.jack.server.JackHttpServer.<init>(JackHttpServer.java:379)
at com.android.jack.server.JackServerImpl.run(JackServerImpl.java:61)
... 2 more
发现是配置文件的权限不对造成的,把文件$HOME/.jack-server/config.properties
的权限由rwx改为rw即可解决问题。
chmod 600 $HOME/.jack-server/config.properties $HOME/.jack-settings
如果说我的文章对你有用,只不过是我站在巨人的肩膀上再继续努力罢了。