diff --git a/README.md b/README.md index e9baa6490..47cf577a8 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ - **APK Checker:** - Analyse the APK package, give suggestions of reducing the APK size; Compare two APK and find out the most significant growth + Analyse the APK package, give suggestions of reducing the APK's size; Compare two APK and find out the most significant increment on size - **Resource Canary:** @@ -25,12 +25,12 @@ - **IO Canary:** - Detect the file IO issues, including performance of file io and closeable leak + Detect the file IO issues, including performance of file IO and closeable leak ## Features ### APK Checker -- **Easy-to-use.** Matrix provides a JAR tool, which is more convenient to apply to your integration systems. +- **Easy-to-use.** Matrix provides a JAR tool, which is more convenient to apply to your integration systems. - **More features.** In addition to APK Analyzer, Matrix find out the R redundancies, the dynamic libraries statically linked STL, unused resources, and supports custom checking rules. - **Visual Outputs.** supports HTML and JSON outputs. @@ -42,38 +42,32 @@ ### Trace Canary -- **High performance.** Dynamically modify bytecode at compile time, record function cost and stack with little performance loss. -- **Accurate stack of ui-block.** Provide informations such as stack, function cost, execution times to solve the problem of ui-block quickly. +- **High performance.** Dynamically modify bytecode at compile time, record function cost and call stack with little performance loss. +- **Accurate call stack of ui-block.** Provide informations such as call stack, function cost, execution times to solve the problem of ui-block quickly. - **Non-hack.** High compatibility to Android versions. - **More features.** Automatically covers multiple fluency indicators such as ui-block, startup time, activity switching, slow function detection. ### SQLite Lint -- **Easy-to-use.** No code intrusion. +- **Easy-to-use.** Non-invasive. - **High applicability.** Regardless of the amount of data, you can discover SQLite performance problems during development and testing. -- **High standards.** Detection algorithms based on best practices, make the quality of SQLite statement high quality. -- **May support multi-platform.** C++ implementation make it possible to support multi-platform. +- **High standards.** Detection algorithms based on best practices, make SQLite statements to the highest quality. +- **May support multi-platform.** Implementing in C++ makes it possible to support multi-platform. ### IO Canary -- **Easy-to-use.** No code intrusion. -- **More feature.** Including performance of file io and closeable leak. +- **Easy-to-use.** Non-invasive. +- **More feature.** Including performance of file IO and closeable leak. - **Compatible with Android P.** ## Getting Started -1. Configure Matrix version in gradle.properties. +1. Configure `MATRIX_VERSION` in gradle.properties. ``` gradle - MATRIX_VERSION=0.4.7 + MATRIX_VERSION=0.4.10 ``` -2. Add matrix-gradle-plugin in your build.gradle: +2. Add `matrix-gradle-plugin` in your build.gradle: ``` gradle - repositories { - maven { - url "https://dl.bintray.com/matrix/maven/" - } - } - dependencies { classpath ("com.tencent.matrix:matrix-gradle-plugin:${MATRIX_VERSION}") { changing = true } } @@ -102,7 +96,7 @@ } ``` -4. Implement PluginListener to receive data processed by Matrix. +4. Implement `PluginListener` to receive data processed by Matrix. ``` java public class TestPluginListener extends DefaultPluginListener { @@ -122,7 +116,7 @@ } ``` -5. Implement DynamicConfig to change parametes of Matrix. +5. Implement `DynamicConfig` to change parametes of Matrix. ``` java public class DynamicConfigImplDemo implements IDynamicConfig { public DynamicConfigImplDemo() {} @@ -158,8 +152,8 @@ } } -``` 6. Init Matrix in the ```onCreate``` of your application. + ``` java Matrix.Builder builder = new Matrix.Builder(application); // build matrix builder.patchListener(new TestPluginListener(this)); // add general pluginListener @@ -185,7 +179,8 @@ You can get more about Matrix output at the wiki [The output of Matrix](https:// ### APK Checker Usage - APK Checker can run independently in Jar ([matrix-apk-canary-0.4.10.jar](https://dl.bintray.com/matrix/maven/com/tencent/matrix/matrix-apk-canary/0.4.10/matrix-apk-canary-0.4.10.jar)) mode, usage: +APK Checker can run independently in Jar ([matrix-apk-canary-0.4.10.jar](https://jcenter.bintray.com/com/tencent/matrix/matrix-apk-canary/0.4.10/matrix-apk-canary-0.4.10.jar)) mode, usage: + ```shell java -jar matrix-apk-canary-0.4.10.jar @@ -232,7 +227,7 @@ Any problem? 1. Learn more from [Sample](https://github.com/Tencent/matrix/tree/master/samples/sample-android) 2. [Source Code](https://github.com/Tencent/matrix/tree/master) -3. [Wiki](https://github.com/Tencent/matrix/wiki) 或 [FAQ](https://github.com/Tencent/Matrix/wiki/Matrix-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) +3. [Wiki](https://github.com/Tencent/matrix/wiki) & [FAQ](https://github.com/Tencent/Matrix/wiki/Matrix-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) 4. Contact us for help ## Contributing @@ -303,17 +298,11 @@ Matrix 当前监控范围包括:应用安装包大小,帧率变化,启动 1. 在你项目根目录下的 gradle.properties 中配置要依赖的 Matrix 版本号,如: ``` gradle - MATRIX_VERSION=0.4.7 + MATRIX_VERSION=0.4.10 ``` 2. 在你项目根目录下的 build.gradle 文件添加 Matrix 依赖,如: ``` gradle - repositories { - maven { - url "https://dl.bintray.com/matrix/maven/" - } - } - dependencies { classpath ("com.tencent.matrix:matrix-gradle-plugin:${MATRIX_VERSION}") { changing = true } } @@ -423,7 +412,7 @@ Matrix 分析后的输出字段的含义请查看 [Matrix 输出内容的含义 ### APK Checker -APK Check 以独立的 jar 包提供 ([matrix-apk-canary-0.4.10.jar](https://dl.bintray.com/matrix/maven/com/tencent/matrix/matrix-apk-canary/0.4.10/matrix-apk-canary-0.4.10.jar)),你可以运行: +APK Check 以独立的 jar 包提供 ([matrix-apk-canary-0.4.10.jar](https://jcenter.bintray.com/com/tencent/matrix/matrix-apk-canary/0.4.10/matrix-apk-canary-0.4.10.jar)),你可以运行: ```cmd java -jar matrix-apk-canary-0.4.10.jar diff --git a/codecc.sh b/codecc.sh new file mode 100644 index 000000000..b84b373ec --- /dev/null +++ b/codecc.sh @@ -0,0 +1,5 @@ +cd /home/android/hudson/workspace/open-check/build/repositories/matrix-android/matrix/matrix-android +./gradlew clean compileDebugJavaWithJavac -PforCoverity --no-daemon +./gradlew :matrix-io-canary:build +./gradlew :matrix-sqlite-lint:build + diff --git a/matrix/matrix-android/gradle.properties b/matrix/matrix-android/gradle.properties index db81d2053..8a29ce81f 100644 --- a/matrix/matrix-android/gradle.properties +++ b/matrix/matrix-android/gradle.properties @@ -13,5 +13,5 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Tue Jun 20 10:24:33 CST 2017 -VERSION_NAME_PREFIX=0.4.7 +VERSION_NAME_PREFIX=0.4.8 VERSION_NAME_SUFFIX= diff --git a/matrix/matrix-android/gradle/android-publish.gradle b/matrix/matrix-android/gradle/android-publish.gradle index eb3f340e2..e991b046e 100644 --- a/matrix/matrix-android/gradle/android-publish.gradle +++ b/matrix/matrix-android/gradle/android-publish.gradle @@ -161,7 +161,7 @@ android.libraryVariants.all { variant -> from components.findByName("android${variant.name.capitalize()}") - // artifact sourcesJar + artifact sourcesJar artifact javadocJar artifact jniSymbolsJar diff --git a/matrix/matrix-android/gradle/java-publish.gradle b/matrix/matrix-android/gradle/java-publish.gradle index 5770e12cc..4d8045024 100644 --- a/matrix/matrix-android/gradle/java-publish.gradle +++ b/matrix/matrix-android/gradle/java-publish.gradle @@ -90,7 +90,7 @@ publishing { artifactId = POM_ARTIFACT_ID version = version - // artifact sourcesJar + artifact sourcesJar artifact javadocJar // append additional configurations diff --git a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/job/ApkJob.java b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/job/ApkJob.java index c1b1e48fa..39a450d61 100644 --- a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/job/ApkJob.java +++ b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/job/ApkJob.java @@ -464,7 +464,12 @@ public void run() throws Exception { ApkTask unzipTask = TaskFactory.factory(TaskFactory.TASK_TYPE_UNZIP, jobConfig, new HashMap()); preTasks.add(unzipTask); for (String format : jobConfig.getOutputFormatList()) { - jobResults.add(JobResultFactory.factory(format, jobConfig)); + JobResult result = JobResultFactory.factory(format, jobConfig); + if (result != null) { + jobResults.add(result); + } else { + Log.w(TAG, "Unknown output format name '%s' !", format); + } } execute(); } else { diff --git a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/CountClassTask.java b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/CountClassTask.java index 311b6fce7..bb20c9dae 100644 --- a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/CountClassTask.java +++ b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/CountClassTask.java @@ -121,6 +121,7 @@ public TaskResult call() throws TaskExecuteException { RandomAccessFile dexFile = dexFileList.get(i); DexData dexData = new DexData(dexFile); dexData.load(); + dexFile.close(); ClassRef[] defClassRefs = dexData.getInternalReferences(); Set classNameSet = new HashSet<>(); for (ClassRef classRef : defClassRefs) { diff --git a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/CountRTask.java b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/CountRTask.java index 8cd438298..e53323b34 100644 --- a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/CountRTask.java +++ b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/CountRTask.java @@ -114,6 +114,7 @@ public TaskResult call() throws TaskExecuteException { for (RandomAccessFile dexFile : dexFileList) { DexData dexData = new DexData(dexFile); dexData.load(); + dexFile.close(); ClassRef[] defClassRefs = dexData.getInternalReferences(); for (ClassRef classRef : defClassRefs) { String className = ApkUtil.getNormalClassName(classRef.getName()); diff --git a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/MethodCountTask.java b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/MethodCountTask.java index 1d9a64a09..485b534ae 100644 --- a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/MethodCountTask.java +++ b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/MethodCountTask.java @@ -204,6 +204,7 @@ public TaskResult call() throws TaskExecuteException { for (int i = 0; i < dexFileList.size(); i++) { RandomAccessFile dexFile = dexFileList.get(i); countDex(dexFile); + dexFile.close(); int totalInternalMethods = sumOfValue(classInternalMethod); int totalExternalMethods = sumOfValue(classExternalMethod); JsonObject jsonObject = new JsonObject(); diff --git a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedAssetsTask.java b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedAssetsTask.java index b35b021c8..73a7be882 100644 --- a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedAssetsTask.java +++ b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedAssetsTask.java @@ -36,9 +36,7 @@ import org.jf.dexlib2.dexbacked.DexBackedDexFile; import org.jf.dexlib2.iface.ClassDef; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; -import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -56,7 +54,6 @@ public class UnusedAssetsTask extends ApkTask { private File inputFile; private final List dexFileNameList; - private final List dexFileList; private final Set ignoreSet; private final Set assetsPathSet; private final Set assetRefSet; @@ -66,7 +63,6 @@ public UnusedAssetsTask(JobConfig config, Map params) { type = TaskFactory.TASK_TYPE_UNUSED_ASSETS; dexFileNameList = new ArrayList<>(); ignoreSet = new HashSet<>(); - dexFileList = new ArrayList<>(); assetsPathSet = new HashSet<>(); assetRefSet = new HashSet<>(); } @@ -94,18 +90,12 @@ public void init() throws TaskInitException { } File[] files = inputFile.listFiles(); - try { - if (files != null) { - for (File file : files) { - if (file.isFile() && file.getName().endsWith(ApkConstants.DEX_FILE_SUFFIX)) { - dexFileNameList.add(file.getName()); - RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); - dexFileList.add(randomAccessFile); - } + if (files != null) { + for (File file : files) { + if (file.isFile() && file.getName().endsWith(ApkConstants.DEX_FILE_SUFFIX)) { + dexFileNameList.add(file.getName()); } } - } catch (FileNotFoundException e) { - throw new TaskInitException(e.getMessage(), e); } } diff --git a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedResourcesTask.java b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedResourcesTask.java index eddbabad7..0b12f43b8 100644 --- a/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedResourcesTask.java +++ b/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedResourcesTask.java @@ -41,10 +41,8 @@ import java.io.BufferedReader; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -67,7 +65,6 @@ public class UnusedResourcesTask extends ApkTask { private File mappingTxt; private File resMappingTxt; private final List dexFileNameList; - private final List dexFileList; private final Map rclassProguardMap; private final Map resourceDefMap; private final Map> styleableMap; @@ -81,7 +78,6 @@ public UnusedResourcesTask(JobConfig config, Map params) { type = TaskFactory.TASK_TYPE_UNUSED_RESOURCES; dexFileNameList = new ArrayList<>(); ignoreSet = new HashSet<>(); - dexFileList = new ArrayList<>(); rclassProguardMap = new HashMap<>(); resourceDefMap = new HashMap<>(); styleableMap = new HashMap<>(); @@ -131,19 +127,14 @@ public void init() throws TaskInitException { } File[] files = inputFile.listFiles(); - try { - if (files != null) { - for (File file : files) { - if (file.isFile() && file.getName().endsWith(ApkConstants.DEX_FILE_SUFFIX)) { - dexFileNameList.add(file.getName()); - RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); - dexFileList.add(randomAccessFile); - } + if (files != null) { + for (File file : files) { + if (file.isFile() && file.getName().endsWith(ApkConstants.DEX_FILE_SUFFIX)) { + dexFileNameList.add(file.getName()); } } - } catch (FileNotFoundException e) { - throw new TaskInitException(e.getMessage(), e); } + } private String parseResourceId(String resId) { diff --git a/matrix/matrix-android/matrix-io-canary/build.gradle b/matrix/matrix-android/matrix-io-canary/build.gradle index f9664cfca..0f3ecd8c4 100644 --- a/matrix/matrix-android/matrix-io-canary/build.gradle +++ b/matrix/matrix-android/matrix-io-canary/build.gradle @@ -15,7 +15,7 @@ android { cppFlags "-std=gnu++11 -frtti -fexceptions" } ndk { - abiFilters "armeabi" + abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64" } } } diff --git a/matrix/matrix-android/matrix-io-canary/src/main/cpp/io_canary_jni.cc b/matrix/matrix-android/matrix-io-canary/src/main/cpp/io_canary_jni.cc index 8822700e9..4cba3abc3 100644 --- a/matrix/matrix-android/matrix-io-canary/src/main/cpp/io_canary_jni.cc +++ b/matrix/matrix-android/matrix-io-canary/src/main/cpp/io_canary_jni.cc @@ -309,6 +309,7 @@ namespace iocanary { __android_log_print(ANDROID_LOG_WARN, kTag, "doHook hook read failed, try __read_chk"); if (!elfhook_replace(soinfo, "__read_chk", (void*)ProxyRead, (void**)&original_read)) { __android_log_print(ANDROID_LOG_WARN, kTag, "doHook hook failed: __read_chk"); + elfhook_close(soinfo); return false; } } @@ -317,6 +318,7 @@ namespace iocanary { __android_log_print(ANDROID_LOG_WARN, kTag, "doHook hook write failed, try __write_chk"); if (!elfhook_replace(soinfo, "__write_chk", (void*)ProxyWrite, (void**)&original_write)) { __android_log_print(ANDROID_LOG_WARN, kTag, "doHook hook failed: __write_chk"); + elfhook_close(soinfo); return false; } } @@ -346,6 +348,8 @@ namespace iocanary { elfhook_replace(soinfo, "__read_chk", (void*) original_read, nullptr); elfhook_replace(soinfo, "__write_chk", (void*) original_write, nullptr); elfhook_replace(soinfo, "close", (void*) original_close, nullptr); + + elfhook_close(soinfo); } return true; } diff --git a/matrix/matrix-android/matrix-sqlite-lint/matrix-sqlite-lint-android-sdk/build.gradle b/matrix/matrix-android/matrix-sqlite-lint/matrix-sqlite-lint-android-sdk/build.gradle index bcaecc86e..e01dbfbe8 100644 --- a/matrix/matrix-android/matrix-sqlite-lint/matrix-sqlite-lint-android-sdk/build.gradle +++ b/matrix/matrix-android/matrix-sqlite-lint/matrix-sqlite-lint-android-sdk/build.gradle @@ -16,7 +16,7 @@ android { arguments "-Dplatform=android" } ndk { - abiFilters "armeabi", "armeabi-v7a" + abiFilters "armeabi", "armeabi-v7a", "x86" } } } diff --git a/matrix/matrix-android/matrix-sqlite-lint/matrix-sqlite-lint-android-sdk/src/full/cpp/sqlite3_profile_hook.cc b/matrix/matrix-android/matrix-sqlite-lint/matrix-sqlite-lint-android-sdk/src/full/cpp/sqlite3_profile_hook.cc index 24808572a..2958d19d2 100644 --- a/matrix/matrix-android/matrix-sqlite-lint/matrix-sqlite-lint-android-sdk/src/full/cpp/sqlite3_profile_hook.cc +++ b/matrix/matrix-android/matrix-sqlite-lint/matrix-sqlite-lint-android-sdk/src/full/cpp/sqlite3_profile_hook.cc @@ -102,6 +102,8 @@ namespace sqlitelint { } if (!elfhook_replace(soinfo, "sqlite3_profile", (void*)hooked_sqlite3_profile, (void**)&original_sqlite3_profile)) { LOGW("Failure to hook sqlite3_profile"); + elfhook_close(soinfo); + soinfo = nullptr; return false; } elfhook_close(soinfo); diff --git a/samples/sample-android/app/build.gradle b/samples/sample-android/app/build.gradle index 5b2df0d2a..1af8f1a24 100644 --- a/samples/sample-android/app/build.gradle +++ b/samples/sample-android/app/build.gradle @@ -20,7 +20,7 @@ android { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" ndk { - abiFilters 'armeabi' + abiFilters 'armeabi', 'armeabi-v7a', 'x86' } } diff --git a/samples/sample-android/gradle.properties b/samples/sample-android/gradle.properties index 1aed4b284..437ff0310 100644 --- a/samples/sample-android/gradle.properties +++ b/samples/sample-android/gradle.properties @@ -13,4 +13,4 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Wed Jun 28 12:25:50 AWST 2017 -MATRIX_VERSION=0.4.7 \ No newline at end of file +MATRIX_VERSION=0.4.8 \ No newline at end of file