如何统计应用中各个包下有多少个方法数

https://github.com/KeepSafe/dexcount-gradle-plugin

A Gradle plugin to report the number of method references in your APK or AAR on every build.

This helps you keep tabs on the growth of your app, with an eye to staying under the 65,536 method-reference limit, and avoiding the headache of eliminating methods or enabling multidex.

Usage

in app/build.gradle

buildscript {
    repositories {
        mavenCentral() // or jcenter()
    }

    dependencies {
        classpath ‘com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.7.1‘
    }
}

// make sure this line comes *after* you apply the Android plugin
apply plugin: ‘com.getkeepsafe.dexcount‘

Note

dexcount-gradle-plugin "requires" Java 8 to run. "Requires" means that, while it will technically work if Gradle is being run on Java 7, there are situations where it may crash. This is caused by dependencies we don‘t bundle targeting JRE 8; these cannot be loaded on older runtimes. Attempting to load them will crash Gradle. This currently applies only to counting .aar library projects, but as time goes by the JRE-8-only surface area will only increase.

Sample output

> ./gradlew assembleDebug

...buildspam...
:app:compileDebugSources
:app:preDexDebug UP-TO-DATE
:app:dexDebug
:app:packageDebug
:app:zipalignDebug
:app:assembleDebug
Total methods in MyApp-debug.apk: 58930 (89.92% used)
Total fields in MyApp-debug.apk:  27507 (41.97% used)
Methods remaining in MyApp-debug.apk: 6605
Fields remaining in MyApp-debug.apk:  38028

BUILD SUCCESSFUL

Total time: 33.017 secs

Detailed method counts

By default, a breakdown of method references by package and class will be written to a file under ${buildDir}/outputs/dexcount/${variant}.

For example, an excerpt from our own app (in app/build/outputs/dexcount/debug.txt):

methods  fields   package/class name
5037     1103     android.support.v4
29       1        android.support.v4.accessibilityservice
57       16       android.support.v4.animation
931      405      android.support.v4.app
87       31       android.support.v4.content
139      12       android.support.v4.graphics
116      11       android.support.v4.graphics.drawable
74       9        android.support.v4.internal
74       9        android.support.v4.internal.view
194      35       android.support.v4.media
11       0        android.support.v4.media.routing
156      26       android.support.v4.media.session

Configuration

Dexcount is configurable via a Gradle extension (shown with default values):

in app/build.gradle:

dexcount {
    format = "list"
    includeClasses = false
    includeClassCount = false
    includeFieldCount = true
    includeTotalMethodCount = false
    orderByMethodCount = false
    verbose = false
    maxTreeDepth = Integer.MAX_VALUE
    teamCityIntegration = false
    teamCitySlug = null
    runOnEachPackage = true
    maxMethodCount = 64000
}

Each flag controls some aspect of the printed output:

  • format: The format of the method count output, either "list", "tree", "json", or "yaml".
  • includeClasses: When true, individual classes will be include in the package list - otherwise, only packages are included.
  • includeClassCount: When true, the number of classes in a package will be included in the printed output.
  • includeFieldCount: When true, the number of fields in a package or class will be included in the printed output.
  • includeTotalMethodCount: When true, the total number of methods in the application will be included in the printed output.
  • orderByMethodCount: When true, packages will be sorted in descending order by the number of methods they contain.
  • verbose: When true, the output file will also be printed to the build‘s standard output.
  • maxTreeDepth: Sets the max number of package segments in the output - i.e. when set to 2, counts stop at com.google, when set to 3 you get com.google.android, etc. "Unlimited" by default.
  • teamCityIntegration: When true, Team City integration strings will be printed.
  • teamCitySlug: A string which, if specified, will be added to TeamCity stat names. Null by default.
  • runOnEachPackage: When false, does not run count method during package task. True by default. Synonym for runOnEachAssemble, which is deprecated.
  • maxMethodCount: When set, the build will fail when the APK/AAR has more methods than the max. 0 by default.

Use with Jenkins Plot Plugin

A common use-case is to plot method and field counts across builds. The Jenkins Plot plugin is a general-purpose tool that graphs per-build scalar values through time. It reads java .properties files, CSV files, and XML files. Dexcount generates two files for each variant - a full package list, and a summary CSV file. The summary file is usable as-is with the Jenkins Plot Plugin. You can find it in app/build/outputs/variant.csv (note the .csv extension).

Consult the plugin documentation for details on how to configure it.

Use with Team City

Common case is to enable integration with teamCityIntegration option and add custom statistic graphs in Team City. Key name is generated by pattern DexCount_${variant}_ClassCountDexCount_${variant}_MethodCount and DexCount_${variant}_FieldCount

Technically special strings like ##teamcity[buildStatisticValue key=‘DexCount_universalDebug_MethodCount‘ value=‘62362‘] will be printed.

More about integration in Team City doc

If you have multiple products within one project using Dexcount, the default stat names will conflict with each other. In this case, the teamCitySlug configuration option can be useful. It is a string that, if specified, will be added to stat names according to the following scheme: DexCount_${teamCitySlug}_${variant}_${statName}. Note that you can assign a dynamically-evaluated property, e.g. teamCitySlug = project.name.

Note on Instant Run

dexcount-gradle-plugin does not count methods for Instant Run builds in Android Studio. Instant Run is implemented in such a way that it makes method counts very inaccurate. As of build-tools version 3.0.0, it is no longer possible to access the complete incrementally-built APK at all. For these reasons, Instant Run is not supported.

Snapshot Builds

We host snapshots in the Sonatype OSS repo. They are updated on each commit. As snapshots, they are inherently unstable - use at your own risk! To use them, add the Sonatype Snapshot repo to your repositories:

buildscript {
  repositories {
    // other repos should come first
    maven { url ‘https://oss.sonatype.org/content/repositories/snapshots‘ }
  }

  dependencies {
    classpath ‘com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.7.2-SNAPSHOT‘
  }
}

Building

./gradlew build

Pushing artifacts to Sonatype requires membership in the KeepSafe Sonatype org, which is by employment only. Once you have a login, put it in your private global Gradle file (e.g. ~/.gradle/gradle.properties, along with a valid GPG signing configuration.

Minutia

This plugin creates a task per output, per variant, and configures each task to run after that variant‘s package task. This means that if the package task does not run, no method count will be reported. This also means that counts are done after Proguard is run, if minification is enabled. Dexcount will use the resulting mapping file to de-obfuscate class and package names.

Credits

The Java code from the com.android.dexdeps package is sourced from the Android source tree. Inspired by Mihail Parparita‘s dex-method-counts project, to whom much credit is due.

Copyright 2015-2017 Keepsafe Software, Inc

时间: 2024-12-14 22:23:52

如何统计应用中各个包下有多少个方法数的相关文章

【转】Predicate和Consumer接口– Java 8中java.util.function包下的接口

原文链接 http://ifeve.com/predicate-and-consumer-interface-in-java-util-function-package-in-java-8/ 原文链接 作者:   Mohamed Sanaulla  译者: 李璟([email protected]) 早先我写了一篇<函数式接口>,探讨了部分Java 8中函数式接口的用法.我也提及了Predicate接口属于java.util.function包, 在这篇文章中,我将展示如何应用Predicat

Andriod项目开发实战(1)——如何在Eclipse中的一个包下建新包

最开始是想将各个类分门别类地存放在不同的包中,所以想在项目源码包中新建几个不同功能的包eg:utils.model.receiver等,最后的结果应该是下图左边这样的:   很明显建立项目后的架构是上图右边这样的,所以后面理所当然地选择new-->package,name栏填上activity,然而结果是下面左边这样的... 这样的结果明显与预想的不一样,我们看到activity与com.mukekeweather.app是并行结构,而我们需要的是树状结构的 查了很多资料之后才弄明白这个问题,因

java中通过包名获取该包下的所有class

前面做的在mybatis通过注解自动创建更新表结构的项目,其中在spring加载完毕之后需要去获取所有实体类的class,用来获取实体类属性上的注解,进而分析表结构达到创建修改表结构的目的. 所以就需要一个功能,通过包名获取该包下的所有class,那么直接贴代码: package com.sunchenbin.store.utils; import java.io.File; import java.io.FileFilter; import java.io.IOException; impor

Servlet3.0中WEB-INF\lib下的jar包中的资源可以直接通过浏览器访问

看公司中的一个项目,访问了一个路径: http://127.0.0.1:8080/XXX/v2/jquery-1.8.1.min.js 但是看项目中的web资源并没有这个js文件,甚至连v2这个目录都没得,就觉得奇怪 便看了下web.xml中是否有相应的Filter之类的进行拦截处理,发现也没有,就纳闷了 便想可能会在引用到的jar包里,便打开几个查找下,果然发现了,解惑 目录结构如下: xxx.jar ---com.abc ---META-INF ------MANIFEST.MF -----

JavaSE8基础 不同包下的子类中,创建子类对象可以继承到父类的 受保护/公有方法

os :windows7 x64    jdk:jdk-8u131-windows-x64    ide:Eclipse Oxygen Release (4.7.0)        代码: 父类: package jizuiku; public class Person { void showDefault() { System.out.println("showDefault"); } private void showPrivate() { System.out.println(&

JavaSE8基础 同一个包下的子类,可以访问到父类中的 默认/受保护/公有方法

os :windows7 x64    jdk:jdk-8u131-windows-x64    ide:Eclipse Oxygen Release (4.7.0)        代码: 父类: package jizuiku; class Person { void showDefault() { System.out.println("showDefault"); } private void showPrivate() { System.out.println("sh

Andriod项目实战——如何在微信H5棋牌斗牛房卡源码平台租售搭建中的一个包下建新包教程

最开始是想将各个类分门别类地微信H5棋牌斗牛房卡源码平台租售搭网址:h5.fanshubbs.com联系Q1687054422存放在不同的包中,所以想在项目源码包中新建几个不同功能的包eg:utils.model.receiver等,最后的结果应该是下图左边这样的: 很明显建立项目后的架构是上图右边这样的,所以后面理所当然地选择new-->package,name栏填上activity,然而结果是下面左边这样的... 这样的结果明显与预想的不一样,我们看到activity与com.mukekew

[ACM] hdu 3555 Bomb (数位DP,统计1-N中含有“49”的总数)

Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 7187 Accepted Submission(s): 2512 Problem Description The counter-terrorists found a time bomb in the dust. But this time the terrorists impro

java中的&quot;包&quot;机制

完全掌握java中的"包"机制 "包"机制是java中特有的,也是java中最基础的知识.一些初学java的朋友,通常象学其它语言一样从教材上copy一些程序来运行,可是却常常遇到莫名其妙的错误提示.这些问题事实上都出在对"包"的原理不够清楚.本文将就此问题进行深入阐述. 一.为什么java中要有"包"的概念? 以一言概之,java中"包"的引入的主要原因是java本身跨平台特性的需求.因为java中的所有