33

Can i have the count of all methods used in a jar file . My APK uses certain external JARS and there are a number of classes around hundred to be precise.

I have used decompilers like dex2jar JAD and others to name a few ,but they all seem to show methods only in particular class file.

Is there a way i can get a total count ?

freeky9
  • 355
  • 1
  • 4
  • 4

12 Answers12

81

You can convert the jar to a dex file, and then pull the number of method references out of the header. It is stored as an unsigned little endian integer, at offset 88 (0x58).

dx --dex --output=temp.dex orig.jar
cat temp.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d\n"'

Keep in mind that this is the number of unique methods referenced, not the number of method references. In other words, if a particular method is referenced twice in the dex file, it will only be counted once in the count in the header. And when you import this jar into your apk, the method references that are common between the two are deduplicated, so the total method reference count of the final merged apk will be <= the sum of the two.

JesusFreke
  • 19,784
  • 5
  • 65
  • 68
  • I don't seem to have the utility 'dx' where does that come from ? – deepwinter Jul 15 '13 at 10:25
  • 2
    here's my answer : android-sdk-macosx/build-tools/17.0.0/dx – deepwinter Jul 15 '13 at 10:30
  • 1
    Thank you, based on your answere I wrote a script for counting methods in a jar folder: https://gist.github.com/toms972/c83504df2da1176a248a – Tom Susel Jul 28 '14 at 09:12
  • This wont work on Windows, since windows doesn't have cat command. Here is the answer for Windows users : http://stackoverflow.com/questions/25835397/android-jar-dex-method-count-on-windows – Majstor May 06 '15 at 11:25
  • 2
    No need for cat/head/tail: `hexdump -s 88 -n 4 -e '1/4 "%d\n"' temp.dex` – friederbluemle Nov 22 '16 at 14:08
  • 1
    Using dx is perfectly fine when you have a dex file assembled, but I ran into a situation when I'm above 65k limit and I simply can't assemble the dex file to examine the method count. Question still stands, how to obtain method count directly from jar without intermediate dex – Gena Batsyan Jul 27 '17 at 17:19
  • 1
    @GenaBatsyan That's a good point. My goal with this answer was to provide a solution using tools that most developers likely already have on their machine (at least, on a unix-like machine, with the android sdk installed). However, see the alternate answer I just added for the case you describe, which uses dx and baksmali. – JesusFreke Jul 27 '17 at 21:22
11

This gradle plugin https://github.com/KeepSafe/dexcount-gradle-plugin will show you the total method count after assembling and also generates a report with the method count of each package. Which after being sorted looks like this:

30145    com
27704    org
20950    android
17140    org.spongycastle
16605    android.support
9760     com.google
8930     com.fasterxml.jackson
8930     com.fasterxml
8633     android.support.v4
7020     com.fasterxml.jackson.databind
6426     android.support.v7
5311     com.google.protobuf
4705     org.spongycastle.crypto
...

In combination with the gradle command

.\gradlew app:dependencies

which prints out the dependency tree you will get a good overview of which dependency needs how many methods.

Sofi Software LLC
  • 3,879
  • 1
  • 36
  • 34
Patrick
  • 33,984
  • 10
  • 106
  • 126
3

Cyvis can read a .jar or .class file, and will show both total method counts plus cyclomatic complexity and instruction count for each method. The GUI is a bit ... portable ... but I've run it on Ubuntu and it says it works on Windows. Seems pretty good for a first-cut source of info on how likely a library is to give you trouble.

Jon Shemitz
  • 1,235
  • 13
  • 29
  • I tried this tool. It would be useful if it sorted things (the packages are in random order), and if you could see totals for number of classes and methods within a package and its sub-packages recursively. It doesn't show the total methods for the whole project; just total packages and classes. – voxoid Jan 02 '17 at 17:49
  • Other issues with this tool: 1) not updated since 2006. 2) doesn't break out internal classes, just top level classes. e.g., my outer class has 8 methods, but an inner class may have 50 more that aren't mentioned. – Jesse Chisholm Jan 05 '17 at 19:52
3

Use the http://github.com/mihaip/dex-method-counts for calculationg number of methods from everywhere (JAR, AAR, DEX, APK)

DEX or APK:

./dex-method-counts <your_file_path>.DEX or ./dex-method-counts <your_file_path>.APK

JAR

just make a DEX from JAR as it was shown above like this:

<your_path_to_android_buil_tools>/dx --dex --output=temp.dex orig.jar

and then

./dex-method-counts temp.dex

AAR

Firstly unzip it (yeah AAR it is ZIP actually) and then use classes.jar as it shown above in JAR section

unzip mylib.aar -d mylib

dx --dex --output=temp.dex mylib/classes.jar

dex-method-counts temp.dex

Alexander Skvortsov
  • 2,696
  • 2
  • 17
  • 31
2

For cases where you're already over the 64k method limit, an alternate approach would be to use the --multi-dex option to dx, and then use baksmali's "list methods" functionality on all of the dex files that dx generates. Next, you would combine these lists, sort the combined list and remove any duplicates. The number of methods you are left with will be the total method count.

dx --dex --multi-dex --output=out orig.jar
find out -name classes*.dex -exec baksmali list methods {} \; | sort | uniq | wc -l
JesusFreke
  • 19,784
  • 5
  • 65
  • 68
0

If you have the source code (or can download it), Sonar will do static analysis like this on it. You can also check a bunch of other complexity metrics which may be useful for what you're trying to do. (Might be nice to tell us what you're trying to do. ;) )

Barett
  • 5,826
  • 6
  • 51
  • 55
  • I am guessing the OP wants to know which JAR files it is worth the time to try and reduce the method count so the final APK remains under the 64K limit. – Jesse Chisholm Jan 05 '17 at 19:57
0
  1. Use the jar program with the -x parameter to extract the files from your jar file.

  2. Apply a decompiler to each .class file to get the number of methods in each file.

  3. Add up the method counts.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
  • Weird, I apparently downvoted this (I don't remember doing so, bad mouse click?). If you edit the post I can change my vote. Sorry :( – powerj1984 Feb 04 '14 at 14:30
  • 1
    @powerj1984 No big deal - I've got plenty of points for my purposes. But I've done a dummy edit, so you can tidy it up. – Patricia Shanahan Feb 04 '14 at 16:10
0

I just wrote a python script for this to get a rough estimate

import re
import subprocess
import sys

for jarfile in sys.argv[1:]:
    class_output = subprocess.check_output(['jar', 'tf', jarfile])
    classes = [c.replace('/', '.') for c in re.findall(r'(.*)\.class', class_output)]
    methods = []
    if classes:
        def_out = subprocess.check_output(['javap', '-classpath', jarfile] + classes)
        # This is pretty hacky: look for parentheses in the declaration line.
        num_methods = sum(1 for line in def_out if '(' in line)
    else:
        num_methods = 0
    print '{} {} {}'.format(num_methods, len(classes), jarfile)

I had just run into the Android 64K method limit, and my dependencies weren't indexed by the methodcount.com service yet.

matt
  • 1,895
  • 5
  • 19
  • 26
  • You could avoid the hack on parenthesis by using the -s flag of javap and look for lines starting with Signature: ( – BP8467 Jan 27 '17 at 14:25
0

I wrote a script based on @JesusFreke's answer for this problem and for another problem (https://stackoverflow.com/a/21485222/6643139):

#!/bin/bash
unzip $1 classes.jar -d aarsize &&
  dx --dex --output=aarsize/temp.dex aarsize/classes.jar &&
  hexdump -s 88 -n 4 -e '1/4 "%d\n"' aarsize/temp.dex &&
  rm -rf aarsize

Save it to a file name "aarsize", chmod +x for it, output of aarsize your_aar_file :

$ aarsize status-bar-compat-release.aar 
Archive:  status-bar-compat-release.aar
  inflating: aarsize/classes.jar     
91

The 91 is the method counts of your aar file.

Community
  • 1
  • 1
黄浩杭
  • 11
  • 2
0

To find methods count in gradle library, you can use this - http://www.methodscount.com

It also provides plugin for android studio.

http://www.methodscount.com/plugins

Zeero0
  • 2,602
  • 1
  • 21
  • 36
-1

With the command line, after having unzipped the JAR, something like this should work :

for f in *.class; do javap -c $(basename -s .class $f) | grep invoke | sed 's/.*Method\(.*\)/\1/g'; done | wc -l
F.X.
  • 6,809
  • 3
  • 49
  • 71
-2
(public|protected|private|static|\s) +[\w\<\>\[\]]+\s+(\w+) *\([^\)]*\) *(\{?|[^;])

Search in project using CTRL+SHIFT+F. It helped me