Как — то раз, бродя по просторам интернета, я наткнулся на PMD. PMD служит для поиска «общих недостатков» кода, таких как пустые блоки, создание объекта, который никогда не используется, и так далее. Кроме того, в составе PMD присутствует CPD(copy-paste-detector), который может находить дублирование кода. PMD полностью поддерживает такие языки как Java, JavaScript, XML, XSL, а CPD может работать и с более длинным списком технологий: Java, C, C + +, C #, PHP, Ruby, Fortran, JavaScript.
Стало интересно, а сколько же таких «общих недостатков» можно найти скажем в 30 приложениях Android, которые спокойно лежат себе на 4pda?
1. Необходимо преобразовать .apk в .jar.
Для этого нужно использовать всем известную dex2jar. Использовать ее очень просто: распаковываем, да пишем примерно следующее:
./dex2jar.sh имя_вашего_apk.apk.
После процесса преобразования в вашей папке вы найдете файл — «имя_вашего_apk_dex2jar.jar». В этом архиве уже лежат классы, необходимые для последующего анализа, но в не читабельном виде, так сказать. Для того, чтобы мы могли как следует покопаться в нормальных классах, нужно их декомпилировать.
2. Преобразовываем код из бинарников в читаемый вид.
Из всех проверенных мной преобразователей самым удачным выглядит fernflower. Чтобы воспользоваться им, нужно выполнить команду:
java -jar fernflower.jar имя_вашего_apk_dex2jar.jar имя_директории
Создастся папка с названием «имя_директории», в которой будет лежать файл с таким же именем, как и исходный. Но в этом случае код можно анализировать.
3. Распаковка архива.
Jar и apk файлы являются архивами, так что их можно запросто распаковать с помощью утилиты unzip.
unzip имя_файла -d имя_директории
4. Натравливаем PMD.
Для анализа исходного кода PMD использует определенный набор правил. Весь список можно глянуть вот тут: правила. Но мы будем использовать всего два набора: android и basic. Для анализа нужно прописать следующую строчку:
./run.sh pmd -d + имя_директории_с_исходниками -f text -R rulesets/java/basic.xml,rulesets/java/android.xml -version 1.7 -language java
В общем — то все, осталось лишь объединить все шаги в единый скрипт и подвести статистику.
5. Пишем простой скрипт на python.
Сначала обговорим структуру проекта. В корне пусть будут папки: apks(куда мы положим 30 наших произвольных apk'ашек), dex2jar(где будет лежать распакованная одноименная программа), pmd(куда распакуем архив с pmd), наш сприпт.
После работы скрипта, мы получим как статистику в текстовом виде, так и диаграмму(диаграмма строится при помощи самого популярного средства под Python — matplotlib).
6. Что же все — таки получилось?
А вышло примерно следующее:
Avoid empty synchronized blocks — 2099
Avoid instantiating Boolean objects; reference Boolean.TRUE or Boolean.FALSE or call Boolean.valueOf() instead. — 269
Avoid using a branching statement as the last in a loop. — 170
Dont create instances of already existing BigInteger and BigDecimal (ZERO, ONE, TEN) — 10
Empty initializer was found — 41
Empty static initializer was found — 41
Ensure you override both equals() and hashCode() — 149
Invoke equals() on the object you've already ensured is not null — 9
Overriding method merely calls super — 310
The null check here is misplaced; if the variable is null there will be a NullPointerException — 10
These nested if statements could be combined — 22
Unnecessary final modifier in final class — 7501
Useless parentheses. — 3582
An empty statement (semicolon) not part of a loop — 4144
Do not hard code the IP address — 101
Do not hardcode /sdcard. — 11
Do not use if statements that are always true or always false — 21
An operation on an Immutable object (String, BigDecimal or BigInteger) wont change the object itself — 4
super should be called at the end of the method — 72
super should be called at the start of the method — 86
Выводы можете делать сами. Мой же вывод такой:
1. PMD достоин того, чтобы использовать его повсеместно, так как таким образом можно избежать не только дублирование кода и создание неиспользуемых переменных, но и выявить более серьезные ошибки.
2. Прогоняйте ваш код через обфускатор. Желательно всегда.
Ссылки:
PMD: pmd
dex2jar: dex2jar
Стало интересно, а сколько же таких «общих недостатков» можно найти скажем в 30 приложениях Android, которые спокойно лежат себе на 4pda?
1. Необходимо преобразовать .apk в .jar.
Для этого нужно использовать всем известную dex2jar. Использовать ее очень просто: распаковываем, да пишем примерно следующее:
./dex2jar.sh имя_вашего_apk.apk.
После процесса преобразования в вашей папке вы найдете файл — «имя_вашего_apk_dex2jar.jar». В этом архиве уже лежат классы, необходимые для последующего анализа, но в не читабельном виде, так сказать. Для того, чтобы мы могли как следует покопаться в нормальных классах, нужно их декомпилировать.
2. Преобразовываем код из бинарников в читаемый вид.
Из всех проверенных мной преобразователей самым удачным выглядит fernflower. Чтобы воспользоваться им, нужно выполнить команду:
java -jar fernflower.jar имя_вашего_apk_dex2jar.jar имя_директории
Создастся папка с названием «имя_директории», в которой будет лежать файл с таким же именем, как и исходный. Но в этом случае код можно анализировать.
3. Распаковка архива.
Jar и apk файлы являются архивами, так что их можно запросто распаковать с помощью утилиты unzip.
unzip имя_файла -d имя_директории
4. Натравливаем PMD.
Для анализа исходного кода PMD использует определенный набор правил. Весь список можно глянуть вот тут: правила. Но мы будем использовать всего два набора: android и basic. Для анализа нужно прописать следующую строчку:
./run.sh pmd -d + имя_директории_с_исходниками -f text -R rulesets/java/basic.xml,rulesets/java/android.xml -version 1.7 -language java
В общем — то все, осталось лишь объединить все шаги в единый скрипт и подвести статистику.
5. Пишем простой скрипт на python.
Сначала обговорим структуру проекта. В корне пусть будут папки: apks(куда мы положим 30 наших произвольных apk'ашек), dex2jar(где будет лежать распакованная одноименная программа), pmd(куда распакуем архив с pmd), наш сприпт.
После работы скрипта, мы получим как статистику в текстовом виде, так и диаграмму(диаграмма строится при помощи самого популярного средства под Python — matplotlib).
6. Что же все — таки получилось?
А вышло примерно следующее:
Avoid empty synchronized blocks — 2099
Avoid instantiating Boolean objects; reference Boolean.TRUE or Boolean.FALSE or call Boolean.valueOf() instead. — 269
Avoid using a branching statement as the last in a loop. — 170
Dont create instances of already existing BigInteger and BigDecimal (ZERO, ONE, TEN) — 10
Empty initializer was found — 41
Empty static initializer was found — 41
Ensure you override both equals() and hashCode() — 149
Invoke equals() on the object you've already ensured is not null — 9
Overriding method merely calls super — 310
The null check here is misplaced; if the variable is null there will be a NullPointerException — 10
These nested if statements could be combined — 22
Unnecessary final modifier in final class — 7501
Useless parentheses. — 3582
An empty statement (semicolon) not part of a loop — 4144
Do not hard code the IP address — 101
Do not hardcode /sdcard. — 11
Do not use if statements that are always true or always false — 21
An operation on an Immutable object (String, BigDecimal or BigInteger) wont change the object itself — 4
super should be called at the end of the method — 72
super should be called at the start of the method — 86
Выводы можете делать сами. Мой же вывод такой:
1. PMD достоин того, чтобы использовать его повсеместно, так как таким образом можно избежать не только дублирование кода и создание неиспользуемых переменных, но и выявить более серьезные ошибки.
2. Прогоняйте ваш код через обфускатор. Желательно всегда.
Ссылки:
PMD: pmd
dex2jar: dex2jar
Комментариев нет:
Отправить комментарий