Puis-je avoir le nombre de toutes les méthodes utilisées dans un fichier jar. Mon APK utilise certains JARS externes et il y a un certain nombre de classes une centaine pour être précis.
J'ai utilisé des décompilateurs comme dex2jar JAD et d'autres pour n'en nommer que quelques-uns, mais ils semblent tous montrer des méthodes uniquement dans un fichier de classe particulier.
Existe-t-il un moyen d'obtenir un nombre total?
Vous pouvez convertir le fichier jar en fichier dex, puis extraire le nombre de références de méthode de l'en-tête. Il est stocké sous la forme d'un petit entier endian non signé, à l'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"'
Gardez à l'esprit qu'il s'agit du nombre de méthodes uniques référencées et non du nombre de références de méthode. En d'autres termes, si une méthode particulière est référencée deux fois dans le fichier dex, elle ne sera comptée qu'une seule fois dans le décompte de l'en-tête. Et lorsque vous importez ce pot dans votre apk, les références de méthode qui sont communes entre les deux sont dédupliquées, donc le nombre total de références de méthode de l'apk fusionné final sera <= la somme des deux.
Ce plugin gradle https://github.com/KeepSafe/dexcount-gradle-plugin vous montrera le nombre total de méthodes après l'assemblage et génère également un rapport avec le nombre de méthodes de chaque package. Ce qui après avoir été trié ressemble à ceci:
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
...
En combinaison avec la commande gradle
.\gradlew app:dependencies
qui imprime l'arborescence des dépendances, vous obtiendrez un bon aperçu de la dépendance qui a besoin de combien de méthodes.
Cyvis peut lire un .jar
ou .class
fichier et affichera à la fois le nombre total de méthodes plus la complexité cyclomatique et le nombre d'instructions pour chaque méthode. L'interface graphique est un peu ... portable ... mais je l'ai exécutée sur Ubuntu et il dit que cela fonctionne sur Windows. Semble assez bon pour une source d'informations de première coupe sur la probabilité qu'une bibliothèque vous cause des problèmes.
Utilisez le http://github.com/mihaip/dex-method-counts pour calculer le nombre de méthodes de partout (JAR, AAR, DEX, APK)
./dex-method-counts <your_file_path>.DEX
ou ./dex-method-counts <your_file_path>.APK
il suffit de faire un DEX à partir de JAR comme indiqué ci-dessus comme ceci:
<your_path_to_Android_buil_tools>/dx --dex --output=temp.dex orig.jar
puis
./dex-method-counts temp.dex
Décompressez-le d'abord (ouais AAR c'est Zip en fait) puis utilisez classes.jar comme indiqué ci-dessus dans la section JAR
unzip mylib.aar -d mylib
dx --dex --output=temp.dex mylib/classes.jar
dex-method-counts temp.dex
Pour les cas où vous avez déjà dépassé la limite de 64 Ko, une autre approche consisterait à utiliser l'option --multi-dex pour dx, puis à utiliser la fonctionnalité "list methods" de baksmali sur tous les fichiers dex générés par dx. Ensuite, vous devez combiner ces listes, trier la liste combinée et supprimer tous les doublons. Le nombre de méthodes qui vous reste sera le nombre total de méthodes.
dx --dex --multi-dex --output=out orig.jar
find out -name classes*.dex -exec baksmali list methods {} \; | sort | uniq | wc -l
Si vous avez le code source (ou pouvez le télécharger), Sonar fera une analyse statique comme celle-ci. Vous pouvez également vérifier un tas d'autres mesures de complexité qui peuvent être utiles pour ce que vous essayez de faire. (Ce serait bien de nous dire ce que vous essayez de faire.;))
Je viens d'écrire un script python pour cela pour obtenir une estimation approximative
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)
Je venais de rencontrer la limite de la méthode Android 64K, et mes dépendances n'étaient pas encore indexées par le service methodcount.com.
Pour trouver le nombre de méthodes dans la bibliothèque Gradle, vous pouvez utiliser ceci - http://www.methodscount.com
Il fournit également un plugin pour Android studio.
Utilisez le programme jar avec le paramètre -x pour extraire les fichiers de votre fichier jar.
Appliquez un décompilateur à chaque fichier .class pour obtenir le nombre de méthodes dans chaque fichier.
Additionnez le nombre de méthodes.
J'ai écrit un script basé sur la réponse de @ JesusFreke pour ce problème et pour un autre problème ( 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
Enregistrez-le sous un nom de fichier "aarsize", chmod +x
pour cela, sortie de aarsize your_aar_file
:
$ aarsize status-bar-compat-release.aar
Archive: status-bar-compat-release.aar
inflating: aarsize/classes.jar
91
Le 91
est le nombre de méthodes de votre fichier aar.