问题
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 ?
回答1:
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.
回答2:
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.
回答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.
回答4:
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
回答5:
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
回答6:
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. ;) )
回答7:
Use the jar program with the -x parameter to extract the files from your jar file.
Apply a decompiler to each .class file to get the number of methods in each file.
Add up the method counts.
回答8:
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.
回答9:
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.
回答10:
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
回答11:
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
回答12:
(public|protected|private|static|\s) +[\w\<\>\[\]]+\s+(\w+) *\([^\)]*\) *(\{?|[^;])
Search in project using CTRL+SHIFT+F
. It helped me
来源:https://stackoverflow.com/questions/14023397/is-there-a-way-to-get-count-of-number-methods-used-in-a-jar-file