在Android的makefile编译系统中,编译结果是多种多样的,这个可以从build/make/core/config.mk
中看出,部分代码如下所示:
BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
BUILD_HEADER_LIBRARY:= $(BUILD_SYSTEM)/header_library.mk
BUILD_AUX_STATIC_LIBRARY:= $(BUILD_SYSTEM)/aux_static_library.mk
BUILD_AUX_EXECUTABLE:= $(BUILD_SYSTEM)/aux_executable.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk
BUILD_RRO_PACKAGE:= $(BUILD_SYSTEM)/build_rro_package.mk
BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk
BUILD_NATIVE_BENCHMARK := $(BUILD_SYSTEM)/native_benchmark.mk
BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
BUILD_FUZZ_TEST := $(BUILD_SYSTEM)/fuzz_test.mk
BUILD_HOST_FUZZ_TEST := $(BUILD_SYSTEM)/host_fuzz_test.mk
BUILD_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/shared_test_lib.mk
BUILD_HOST_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/host_shared_test_lib.mk
BUILD_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/static_test_lib.mk
BUILD_HOST_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/host_static_test_lib.mk
BUILD_NOTICE_FILE := $(BUILD_SYSTEM)/notice_files.mk
BUILD_HOST_DALVIK_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_java_library.mk
BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_static_java_library.mk
BUILD_HOST_TEST_CONFIG := $(BUILD_SYSTEM)/host_test_config.mk
BUILD_TARGET_TEST_CONFIG := $(BUILD_SYSTEM)/target_test_config.mk
在Android.mk中的用法如下所示:
include $(BUILD_XXX)
下面介绍Java相关的BUILD_JAVA_LIBRARY
和BUILD_STATIC_JAVA_LIBRARY
。
BUILD_STATIC_JAVA_LIBRARY
BUILD_STATIC_JAVA_LIBRARY
表示编译结果为Java静态库,更准确地说就是一个与Android无关的纯Java包。
以模块名即LOCAL_MODULE
是abc
为例,使用aapt
进行编译。Android默认使用jack
进行编译,使用aapt进行编译的方法是LOCAL_JACK_ENABLED := disabled
。
编译完成后,编译结果如下所示:
out/target/product/product_name/obj/JAVA_LIBRARIES/abc_intermediates
└── javalib.jar
out/target/common/obj/JAVA_LIBRARIES/abc_intermediates
├── anno 空目录,应该是annotation相关的。
├── classes 里面是所有的class文件。
├── classes-full-debug.jar
├── classes.jar
└── link_type 内容为java:platform
product目录下只有一个javalib.jar
,这个是从common目录下直接拷贝过来的,只是改了个名字而已。
javalib.jar
是一个Java包,可以用解压缩工具打开,也可以从命令行用jar
命令解压缩或直接查看里面的文件。解压缩命令jar -xvf javalib.jar
,直接查看命令jar -tvf javalib.jar
。其中有两类文件,一类是纯文本文件manifest,另一类是class为后缀的编译过的Java类数据文件。class文件中的部分内容可以从命令行用Java反编译工具javap
进行查看,javap xxx.class
。
common目录下的两个jar包是一样的,同product目录下的javalib.jar
。
BUILD_JAVA_LIBRARY
BUILD_JAVA_LIBRARY
表示编译结果为Java动态库,更准确地说是应用于Android的Java包。
编译完成后,编译结果如下所示:
out/target/product/product_name/obj/JAVA_LIBRARIES/abc_intermediates
└── javalib.jar
out/target/product/product_name/system/framework/abc.jar
out/target/common/obj/JAVA_LIBRARIES/abc_intermediates
├── anno 空目录,应该是annotation相关的。
├── classes 里面是所有的class文件。
├── classes-desugar.jar desugar即脱糖,为了兼容性,如将Java8的lambda表达式转换为普通表达式。
├── classes.dex
├── classes-full-debug.jar 非脱糖的原始class。
├── classes.jar 同desugar。
├── desugar_dumped_classes 空目录,desugar相关。
├── javalib.jar
├── link_type 内容为java:platform
└── with-local 空目录,local相关。
product目录下的javalib.jar和abc.jar是相同的,里面有两个文件,manifest和classes.dex。可以看出,Java动态库中的class文件变成了静态库中的dex文件,dex文件是Android Dalvik特有的文件格式。
上面介绍了Java库的两个不同的编译结果,下面介绍使用方式。
Java库有两种使用方式,LOCAL_JAVA_LIBRARIES
和LOCAL_STATIC_JAVA_LIBRARIES
。
LOCAL_STATIC_JAVA_LIBRARIES
LOCAL_STATIC_JAVA_LIBRARIES
表示把引用的外部Java库(可以是上面提到的两种形式的Java库)直接编译打包到本模块中,在runtime时可以直接从本模块中找到相关的东西。
LOCAL_JAVA_LIBRARIES
LOCAL_JAVA_LIBRARIES
表示引用的外部Java库(可以是上面提到的两种形式的Java库)在编译时可以找到相关的东西,但并不打包到本模块,在runtime时需要从别的地方查找,这个别的地方就是在编译时将引用的外部Java库的模块名添加到PRODUCT_BOOT_JARS
,例如Android原生的framework.jar
就添了,PRODUCT_BOOT_JARS+=framework
,否则在runtime时ClassLoader找不到需要的class。
综上,Android中所谓的Java动态库、静态库不同于C、C++的动态库、静态库,编译为静态库时表示编译为原生的Java class压缩包,编译为动态库时表示编译为用于Android Dalvik的dex压缩包,静态引用时把外部库直接打包过来,动态引用时需要将外部库加到PRODUCT_BOOT_JARS
。