Есть ли способ получить количество методов, используемых в файле jar?
Могу ли я иметь количество всех методов, используемых в JAR-файле. Мой APK использует определенные внешние JARS, и существует несколько классов, если быть точным.
Я использовал такие декомпиляторы, как dex2jar JAD и другие, но все они, кажется, показывают методы только в определенном файле класса.
Есть ли способ, которым я могу получить общий счет?
12 ответов
Вы можете преобразовать jar-файл в dex-файл, а затем извлечь количество ссылок на методы из заголовка. Он сохраняется как целое число без знака с прямым порядком байтов по смещению 88 (0x58).
dx --dex --output=temp.dex orig.jar
cat temp.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d\n"'
Имейте в виду, что это количество уникальных методов, на которые ссылаются, а не количество ссылок на методы. Другими словами, если на конкретный метод ссылаются дважды в файле dex, он будет засчитан только один раз при подсчете в заголовке. И когда вы импортируете этот jar-файл в ваш apk, ссылки на методы, которые являются общими для двух, дедуплицируются, поэтому общее число ссылок на метод в окончательном объединенном apk будет <= сумма двух.
Этот плагин gradle https://github.com/KeepSafe/dexcount-gradle-plugin покажет вам общее количество методов после сборки, а также создаст отчет с количеством методов каждого пакета. Который после сортировки выглядит так:
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
...
В сочетании с командой gradle
.\gradlew app:dependencies
который распечатывает дерево зависимостей, вы получите хороший обзор того, какая зависимость нуждается в том, сколько методов.
Используйте http://github.com/mihaip/dex-method-counts для расчета количества методов отовсюду (JAR, AAR, DEX, APK)
DEX или APK:
./dex-method-counts <your_file_path>.DEX
или же./dex-method-counts <your_file_path>.APK
JAR
просто создайте DEX из JAR, как показано выше, вот так:
<your_path_to_android_buil_tools>/dx --dex --output=temp.dex orig.jar
а потом
./dex-method-counts temp.dex
AAR
Сначала распакуйте его (да, на самом деле это AAR), а затем используйте классы.jar, как показано выше в разделе JAR.
unzip mylib.aar -d mylib
dx --dex --output=temp.dex mylib/classes.jar
dex-method-counts temp.dex
Cyvis может прочитать .jar
или же .class
файл, и покажет общее количество методов плюс цикломатическую сложность и количество команд для каждого метода. Графический интерфейс немного... переносимый... но я запускаю его в Ubuntu, и он говорит, что он работает в Windows. Кажется, это неплохо для первоисточника информации о вероятности возникновения проблем у библиотеки.
В тех случаях, когда вы уже превысили ограничение в 64 КБ, альтернативным подходом будет использование опции --multi-dex для dx, а затем использование функциональности "списочных методов" baksmali для всех файлов dex, которые генерирует dx. Затем вы должны объединить эти списки, отсортировать объединенный список и удалить любые дубликаты. Количество оставленных вами методов будет общим количеством методов.
dx --dex --multi-dex --output=out orig.jar
find out -name classes*.dex -exec baksmali list methods {} \; | sort | uniq | wc -l
Используйте программу jar с параметром -x, чтобы извлечь файлы из вашего файла jar.
Примените декомпилятор к каждому файлу.class, чтобы получить количество методов в каждом файле.
Сложите метод подсчета.
Я написал скрипт на основе ответа @JesusFreke для этой проблемы и для другой проблемы ( /questions/47652789/kak-konvertirovat-aar-v-jar/47652845#47652845):
#!/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
Сохраните его в файле с именем "aarsize", chmod +x
для него вывод aarsize your_aar_file
:
$ aarsize status-bar-compat-release.aar
Archive: status-bar-compat-release.aar
inflating: aarsize/classes.jar
91
91
это метод подсчета вашего файла aar.
Если у вас есть исходный код (или вы можете его скачать), Sonar выполнит статический анализ, подобный этому. Вы также можете проверить кучу других метрик сложности, которые могут быть полезны для того, что вы пытаетесь сделать. (Может быть, приятно рассказать нам, что вы пытаетесь сделать;)
Чтобы найти количество методов в библиотеке Gradle, вы можете использовать это - http://www.methodscount.com/
Он также предоставляет плагин для Android Studio.
Я просто написал скрипт на Python для этого, чтобы получить приблизительную оценку
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)
Я только что натолкнулся на ограничение метода Android 64K, и мои зависимости еще не были проиндексированы службой methodcount.com.
С командной строкой, после разархивирования JAR, должно работать что-то вроде этого:
for f in *.class; do javap -c $(basename -s .class $f) | grep invoke | sed 's/.*Method\(.*\)/\1/g'; done | wc -l
(public|protected|private|static|\s) +[\w\<\>\[\]]+\s+(\w+) *\([^\)]*\) *(\{?|[^;])
Поиск в проекте с использованием CTRL+SHIFT+F
, Это помогло мне