Instrumentierung von Android Anwendungen in ExplorViz Bachelorarbeit Jan Witzany 30. September 2016 Christian-Albrechts-Universität zu Kiel Institut für Informatik Arbeitsgruppe Software Engineering Betreut durch: Prof. Dr. Wilhelm Hasselbring M.Sc. Christian Zirkelbach Eidesstattliche Erklärung Hiermit erkläre ich an Eides statt, dass ich die vorliegende Arbeit selbstständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel verwendet habe. Kiel, 30. September 2016 ii Zusammenfassung Google’s Android Betriebssystem ist das meist verwendeten Betriebssystem für Smartphones. Durch den wachsenden Markt gibt es viele Anwendungsentwickler. Wie viel andere Programme auch, werden Android Anwendungen im Laufe der Entwicklung häufig größer und komplexer. Hinzu kommt noch, dass oftmals Programme nicht ausreichend dokumentiert sind. Statische Analysen über den Sourecode sind in der Regel langwierig und nicht ausreichend. Wohingegen eine dynamische Analyse viele Vorteile mit sich bringt, so wird nur der Programmcode betrachtet, welcher tatsächlich genutzt wird. Diesen Ansatz verfolgt das Live Trace Visualisierungs Programm ExplorViz. Durch die Online-Analyse und Live Visualisierung gibt ExplorViz ein schnelles Feedback auf die getätigten Eingaben. In dieser Arbeit behandeln wir das Monitoring von Android Anwendungen in ExplorViz. Wir bauen dabei auf bestehende Komponenten auf und passen ExplorViz für Android an. Es ist uns gelungen den Sourcecode einer Applikation mit der erstellten Monitoring-Library zu instrumentieren und in ExplorViz visuell darzustellen. Weiterhin haben wir Ansätze für das Instrumentieren auf Basis von APKs formuliert. iii Inhaltsverzeichnis 1 Einleitung 1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Ziele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Aufbau der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 2 3 2 Grundlagen und Technologien 2.1 Android . . . . . . . . . . . . . . . . . . . . 2.2 Build-Management-Tool . . . . . . . . . . . 2.3 Instrumentierung . . . . . . . . . . . . . . . 2.3.1 Aspektorientierte Programmierung 2.4 ExplorViz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 6 7 7 9 Monitoring Android Applikationen 3.1 Manuelle Instrumentierung . . . . . . . . 3.2 Instrumentation-Klasse . . . . . . . . . . . 3.3 BCEL . . . . . . . . . . . . . . . . . . . . . 3.4 Soot . . . . . . . . . . . . . . . . . . . . . . 3.5 AspectBench Compiler . . . . . . . . . . . 3.6 dex2jar . . . . . . . . . . . . . . . . . . . . 3.7 jadx . . . . . . . . . . . . . . . . . . . . . . 3.8 APKtool . . . . . . . . . . . . . . . . . . . 3.9 Auswahl der Instrumentierungs-Technik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 12 12 13 13 13 14 14 14 15 3 . . . . . . . . . 4 Monitoring in ExplorViz 17 4.1 Aktueller Stand im ExplorViz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.2 Entwurf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5 Implementierung 5.1 Sourcecode Instrumentierung . . . 5.1.1 Build-Skript . . . . . . . . . 5.2 APK Instrumentierung . . . . . . . 5.2.1 Reverse Engineering . . . . 5.2.2 Probleme . . . . . . . . . . . 5.3 Android-Monitoring in ExplorViz 5.4 Kompatibilität mit Android . . . . 5.5 Aspekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 23 23 25 25 25 25 26 29 v Inhaltsverzeichnis 5.6 Variable Pointcuts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 6 Evaluation 31 7 Verwandte Arbeiten 7.1 Kieker Monitoring Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2 SPASS-meter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3 Android Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 35 35 36 8 Fazit und Ausblick 37 8.1 Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 8.2 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Bibliografie 39 Anhang 41 vi Kapitel 1 Einleitung 1.1. Motivation Das Betriebssystem Android1 war 2015 mit einem Marktanteil von über 82% das meist verwendete System für Smartphones [IDC 2015]. Anwendungen für das Betriebssystem werden in der Programmiersprache Java geschrieben und zu Androids eigenem Dateiformat Android package (APK) kompiliert. Durch die hohe Verbreitung kam in den letzten Jahren eine Vielzahl von neuen Applikationen von verschiedenen Entwicklern auf den Markt. Im Laufe der Entwicklung einer Anwendung werden der Programmcode und die einzelnen Module üblicherweise umfangreicher und komplexer. Häufig kommt dazu noch eine mangelhafte oder fehlende Dokumentation. Dieses Problem wird bei Legacy-Anwendungen, welche nur noch gewartet werden und die ursprünglichen Entwickler unter Umständen gar nicht mehr an dem Projekt beteiligt sind, verstärkt. Eine statische Quellcode-Analyse kann sehr zeitaufwendig werden. Einen anderen Ansatz wählt ExplorViz2 . Um das Verständnis für komplexere Anwendungen zu erleichtern, wurde ExplorViz entwickelt[Fittkau u. a. 2013a]. ExplorViz ist eine Software zum Monitoring und zur Visualisierung von Applikationen und deren internen Kommunikation zur Laufzeit, sowie das Messen des Ressourcenverbrauchs. So wurde ExplorViz zum Beispiel für eine PerformanceAnalyse für eine in Perl geschriebene Legacy-Software eingesetzt . Nativ wird bereits die Analyse von Java-Programmen unterstützt. Da Android Applikationen hauptsächlich in der Java geschrieben werden, wird zunächst geklärt, inwiefern die bestehenden Monitoring Methoden für die Instrumentation verwendet werden können, und welche spezifischen Anpassungen vorgenommen werden müssen. 1 https://www.android.com 2 https://www.explorviz.net 1 1. Einleitung 1.2. Ziele In diesem Kapitel werden die Ziele dieser Arbeit erläutert. Ziel 1: Instrumentierung von Android Anwendungen mit der Monitoring Komponente von ExplorViz Das Hauptziel dieser Arbeit besteht darin, die Monitoring-Komponente von ExplorViz so zu erweitern, dass diese auch für das Monitoring von Android Anwendungen eingesetzt werden kann. Die Komponente soll in bereits bestehende Android-Projekten, Sourcecode oder APK eingebunden werden und so zur Laufzeit Informationen über die Methodenaufrufe und Systemressourcen sammeln. Diese gesammelten Informationen sollen in MonitoringRecords zusammengefasst werden und für die Analyse an den ExplorViz-Server geschickt werden, um eine Visualisierung zu ermöglichen. Den Entwicklern soll es mit geringem Aufwand möglich sein ihre Android Applikation instrumentieren zu können. Ziel 1.1: Erweiterung der Monitoring Komponente von ExplorViz Die bereits bestehende Monitoring-Komponente von ExplorViz soll so erweitert werden, dass sie auch für die Instrumentierung von Android verwendet werden kann. Es sind bereits Ansätze dafür vorhanden. Diese sollen angepasst werden um eine einfache Instrumentierung von Android-Anwendungen zu ermöglichen. Ziel 1.2: Instrumentierung von Android Sourcecode Die bestehende Implementierung von ExplorViz verwendet für die Instrumentierung einen Ansatz, der es ermöglicht zur Laufzeit Methoden zum Messen (Probes) in den auszuführenden Code einzuweben. Diese Möglichkeit bietet Android nicht an und das instrumentierte Programm muss bereits zur Installation vollständig vorliegen. Für diese Arbeit muss ein anderer Ansatz gewählt werden. Ziel 1.3: Instrumentierung von APKs Android Anwendungen werden zwar in Java programmiert, besitzen aber ein eigenes Dateiformat. Der Sourcecode wird bei der Erstellung zu Android packages (APK) kompiliert. Wenn der Sourcecode nicht zu Verfügung steht, sollte es möglich sein, die App auch nur auf Grundlage der APK zu instrumentieren. Ziel 2: Evaluation der Instrumentierung von Android Apps Die neu erstellte Komponente für das Android-Monitoring wird an der Android Applikation Babsi getestet und die Ergebnisse ausgewertet und diskutiert. Es wird zum einen auf die generelle Funktionalität der Monitoring-Komponente geprüft. Wie bei der Darstellung von Java Programmen soll es ExplorViz möglich sein die, Klassen und Traces zur Laufzeit der Applikation zu analysieren und darzustellen. Zum anderen wird auf die Usability geachtet, 2 1.3. Aufbau der Arbeit inwiefern Entwickler ihre App ohne großen Aufwand Instrumentieren und Analysieren können. Dabei wird die Monitoring-Komponente auch mit unterschiedlichen Android Versionen getestet, um eine Kompatibilität zu Altsystemen zu gewährleisten. 1.3. Aufbau der Arbeit Im folgenden Kapitel werden zunächst einige Grundlagen zum Arbeiten mit Android und Konzepte für die Instrumentierung erklärt. Anschließend wird im Kapitel 3 auf unterschiedliche Ansätze zum Instrumentieren von Android Applikationen eingegangen. Im Kapitel 4 wird der aktuelle Stand von ExplorViz und insbesondere die MonitoringKomponente dargelegt. Es wird auch ein Entwurf für das Instrumentieren von Android Apps mit ExplorViz vorgestellt. Im nachfolgenden Kapitel 5 wird die Implementierung der Monitoring-Komponente beschrieben. Anschließend findet im Kapitel 6 eine Evaluation statt. Kapitel 7 behandelt verwandte Arbeiten. Das letzte Kapitel beschäftigt sich mit dem Fazit und einem Ausblick. 3 Kapitel 2 Grundlagen und Technologien In diesem Kapitel wird zunächst auf die Eigenschaften von Android eingegangen. Anschließend werden mit Ant und Gradle zwei Build-tools vorgestellt, welche im Laufe dieser Arbeit für die ExplorViz-Library und das Monitoring von Android Anwendungen verwendet werden. Danach wird auf das Programmierparadigma der Aspektorientierung und dessen Implementierung mit AspectJ erläutert. Am Ende wird ein kurzer Überblick über ExplorViz gegeben. 2.1. Android Android ist ein auf dem Linux-Kernel basierendes Betriebssystem für mobile Endgeräte. Das im Jahre 2003 gründete Unternehmen Android, Inc. wurde 2005 von Google gekauft und das Betriebssystem seitdem kontinuierlich weiterentwickelt. Die Anwendungen sind in der Programmiersprache Java geschrieben, wobei nicht alle Libraries und application programming interfaces (APIs) unterstützt werden. Derzeit unterstützt die aktuelle Android-Version die Syntax aus Java Version 7. Weiterhin können Teile der Applikation aus Effizienzgründen auch in C oder C++ programmiert werden. In dieser Arbeit befassen wir uns allerdings mit dem Monitoring von Applikationen basierend auf Java Sourcecode. Im Rahmen der Weiterentwicklung des Betriebssystems unterscheiden sich die einzelnen Versionen von ihren Eigenschaften, und die Funktionsweise wird mit unterschiedlichen Android APIs erweitert. Um eine Abwärtskompatibilität zu gewährleisten, kann eine Minimum- und eine Ziel-Version angegeben werden, die das Kompilerlevel bestimmt und so eine Installation auf Geräten mit verschiedenen Android-Versionen erlaubt. Die Android Version für die kompiliert wird, wird mit dem API Level angegeben. So hat die aktuelle Android Version 7.0 das API Level 24. Im Gegensatz zu einem Java-Programm, welches zu Bytecode kompiliert wird um anschließend auf der Stack-basierten Java Virtual Machine (JVM) ausgeführt zu werden, verfügt Android über eine eigene virtuelle Maschine, die Dalvik Virtual Machine (DVM). Diese basiert aus Performancegründen auf Register anstelle eines Stacks. Deshalb muss der Build-Prozess um einen Schritt erweitert werden und der Java Bytecode mit dem dx-tool zu einer Dalvik executable (classes.dex) kompiliert werden. Die einzelnen .dex-Dateien werden später in einem Executable zusammengefasst und mit weiteren Ressourcen und Metadaten 5 2. Grundlagen und Technologien in das Android Dateiformat Android Package (APK) gepackt. Eine APK kann später auf dem Android Betriebssystem installiert werden. Dabei wird der Bytecode zur Laufzeit (justin-time) in Maschinensprache übersetzt und ausgeführt. Seit dem im November 2014 erschienenen Android 5.0 wird nicht mehr die DVM, sondern die Android Runtime (ART) verwendet. Hier wird der Bytecode nur einmalig, während der Installation der Anwendung in Maschinencode übersetzt (ahead-of-time). Um ältere Anwendungen zu unterstützen wird weiterhin das .dex-Format beibehalten. Um den Autoren, der Android Applikation zu verifizieren, muss die Applikation signiert werden [Arzt u. a. 2013]. Jedes Mal, wenn eine Änderung im Programmcode vorgenommen wurde, muss die APK neu kompiliert werden, und anschließend mit dem gleichen Schlüssel signiert werden. Dies dient dazu, dass sichergestellt wird, dass jede Änderung vom Autor autorisiert ist. Wenn sich der Schlüssel ändert, wird die Applikation vom System als eine andere Applikation angesehen. Während der Kompilierung in Bytecode ist es möglich Programme wie zum Beispiel ProGuard1 zu verwenden. Diese können zum einen den benötigten Speicherplatz reduzieren, indem nicht benötigte Teile des Programmes und der Libraries entfernt werden. Zum anderen soll der Sourcecode verschleiert und so ein Reverse Engineering erschwert werden. Dazu können manche Klassen, Methoden und Variablen umbenannt werden, um nicht direkt von ihrem Namen auf den verwendeten Zweck schließen zu können. 2.2. Build-Management-Tool Um Entwicklungs- und Kompilierungsschritte zu definieren und strukturieren, können Build-Management-Tools eingesetzt werden. Diese ermöglichen ein automatisches Kompilieren in bestimmter Ausführung und Abhängigkeit. Apache Ant 1 ist eine in Java geschrieben Library zur Erstellung und deren Automatisierung von Anwendungen. Dafür werden einzelne Aufgaben in sogenannten Tasks definiert, welche je nach Bedarf in gewünschter Reihenfolge ausgeführt werden können. Es können sowohl vordefinierte als auch eigene Tasks verwendet werden. Standardmäßig wird die Verwendung der benötigten Tasks in einem XML-Dokument mit dem Namen build.xml angeben und dieses Skript dann ausgeführt. ExplorViz verwendet derzeit Ant zum Erstellen der Monitoring-Library. Gradle 3 ist ein auf Java basierendes Build-tool zum Automatisieren von Build-Prozessen. Seit 2013 wird es offiziell von Google für die Entwicklung von Android Anwendungen eingesetzt. Beim Erstellen eines neuen Projektes in der Entwicklungsumgebung Android 1 http://proguard.sourceforge.net 1 http://ant.apache.org/ 3 https://gradle.org/ 6 2.3. Instrumentierung Studio wird automatisch ein Gradle-Skript erstellt und die Ordnerstruktur danach angepasst. Es ist aber auch möglich ältere Projekte, welche zum Beispiel noch Maven verwenden in ein Gradle-Projekt zu importieren. Dabei hat jedes Projekt und Unterprojekt ein eigenes Gradle-Skript. Unterprojekte erben Eigenschaften von dem hierarischen überstehenden Projekten. Gradle wird in einer domänenspezifische Sprache (DSL),welche auf Groovy basiert, geschrieben und akzeptiert jeden validen Groovy-Ausdruck. So können vorhandene oder auch selbstgeschriebene Gradle-Plugins angewendet werden. Weiterhin können auch Ant Tasks und Skripte eingelesen und ausgeführt werden. 2.3. Instrumentierung Beim Monitoring sollen bestimmte Teile einer Anwendung überwacht und Werte aufgezeichnet werden. Diese sollen gesammelt und anschließend analysiert werden. Dazu ist es nötig, Funktionen zu implementieren, die diese Aufgabe übernehmen. Diesen Vorgang nennt man Instrumentierung. Ein naiver Ansatz ist es diese Funktionen manuell an den entsprechenden Stellen im Code einzufügen. Dies hat den Nachteil, dass jeder Messpunkt einzeln angegeben werden muss. Zudem ist die Funktionsweise dieser Methoden häufig sehr ähnlich, sodass redundanter Code erzeugt werden würde. Außerdem wird dabei die Instrumentierungs-Logik mit der Implementierung des eigentlichen Programmes vermischt und widerspricht dem Seperation of concerns. Dies kann die Wartbarkeit des Programmes stark einschränken. 2.3.1. Aspektorientierte Programmierung Es ist also von Vorteil die Instrumentierung zu modularisieren und getrennt vom Sourcecode der Anwendung zu implementieren. Als Ansatz dazu hat unter anderem Kiczales, mit Aspektorientierte Programmierung (AOP) ein Programmierparadigma eingeführt ( [Kiczales u. a. 1997]). Hier wird unter Berücksichtigung des cross-cutting concerns der Code für die Instrumentierung vom eigentlichen Sourcecode der Applikation getrennt. Dazu werden die Funktionen als sogenannte Aspekte definiert. Diese werden an definierten Stellen in den Sourcecode eingewoben. Das Einweben kann beim Kompilieren (Compile-time weaving), nach dem Kompilieren (Postcompile weaving) oder zur Laufzeit (Load-time weaving) geschehen. Für Android ist ein Einweben zur Laufzeit nicht möglich. ExplorViz verwendet mit AspectJ1 [Kiczales u. a. 2001] eine Erweiterung von Java für den aspektorientierten Ansatz. Aspekte werden in Java-Klassen geschrieben und mit Annotationen gekennzeichnet. Die Implementierung umfasst vier Schlüsselwörter: 1 https://eclipse.org/aspectj 7 2. Grundlagen und Technologien Join Poin beschreibt einen Punkt in der ausgeführten Anwendung an dem zusätzlicher Code mit eingewoben werden kann. Pointcut definiert und wählt aus, an welchem JoinPoint Code eingewoben werden soll. Es können verschiedene Schlüsselwörter verwendet werden, sowie reguläre Ausdrücke. So steht execution(* *..*(..) für jeden Methodenaufruf und execution(*..*.new(..)) für jeden Konstruktoraufruf mit beliebiger Anzahl von Argumenten. Mit within kann ein package oder auch eine spezielle Klasse angegeben werden. Außerdem stehen für die Definition eines Pointcutes mit &&, || und ! das logische Und, Oder beziehungsweise Nicht zur Verfügung. Advice nennt sich der Code der zusätzlich eingewoben wird. Zusätzlich wird noch mit angegeben, an welcher Stelle, relativ zum ausgewählten JoinPoint, der zusätzliche Code eingeworben werden soll: before(), after(), around(). Aspekt fasst Pointcuts und Advice in einer Klasse zusammen. Ab AspectJ 5 werden Annotationen erlaubt und es ist möglich Aspekte als Java-Klassen zu definieren. Frühere Versionen verwendeten mit .aj eigene Dateien. Pointcuts definieren also, an welchen Punkten (JoinPoint) in einem Programm neuer Code (Advice) eingefügt werden soll. Das Ganze wird in einem Aspekt definiert. Listing 2.1 beschreibt beispielhaft einen solchen Aspekt. Listing 2.1. Aspect mit Annotation 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Aspect public class Aspect{ @Pointcut("execution(* *(..) && !within(explorviz.**)") public void methodExecution(){} @Around("pointcut()") public void aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable { //code before execution of method JoinPoint.proceed() //code after execution of method } 8 2.4. ExplorViz Die Annotation @Aspect gibt an, dass es sich um einen Aspekt handelt. Mit @Pointcut wird ein Pointcut definiert und in Zeile 8 angwendet. Der Around-Advice wird ausgeführt, wenn der JoinPoint erreicht ist und hat Kontrolle darüber, wann und ob die eigentliche Methode ausgeführt wird. Mit JoinPoint.proceed() muss explizit angeben werden, dass die Methode ausgeführt werden soll. 2.4. ExplorViz ExplorViz ermöglicht eine live Trace Visualisierung von großen Softwarelandschaften [Fittkau 2015]. Die Software verfügt über zwei verschieden Perspektiven. Zum einen die Landschaftsperspektive, welche mit UML Elementen ganz Softwarelandschaften darstellen kann und zum anderen die Applikationsperspektive, welche eine 3D-Softwarestadtmetapher verwendet. In der Applikationsperspektive werden Packages als grüne und Klassen als blaue Kästen dargestellt (vgl. Abbildung 2.1). Von der Höhe der Klassen-Kästen gibt die Anzahl der aktiven Instanzen an. Die Methodenaufrufe, die außerhalb einer Klasse liegen werden mit orangenen Linien gekennzeichnet. Die Breite der Linien drückt dabei die Häufigkeit der entsprechenden Methode aus [Fittkau u. a. 2016]. In der Live-Ansicht kann jeder Zeit pausiert und zu einen zurückliegenden Zeitpunkt gesprungen werden. Abbildung 2.1. ExplorViz: Applikationsperspektive entnommen aus [Fittkau u. a. 2013a] 9 2. Grundlagen und Technologien Das Programm besteht im Wesentlichen aus drei Komponenten: die MonitoringKomponente, die Analyse-Komponente und die Server-Komponente. Zur Laufzeit wird mit Hilfe von AspectJ die Monitoring-Library in die Applikation eingewoben. Diese erstellt Monitoring-Records über Methodenaufrufe und Ressourcenverbrauch des Programms. Diese Records werden über eine TCP-Verbindung an die Analyse-Komponente geschickt. In der Analyse-Komponente werden mit Hilfe der Records sogenannte Traces erstellt, die in einer Visualisierung-Komponente graphisch dargestellt werden können. Durch einen Monitoring Data Adapter lassen sich von anderen Programmen, wie zum Beispiel Kieker [van Hoorn u. a. 2012], erzeugte Records zur Offline-Analyse nutzen. So ist es auch möglich andere Sprache als Java, wie zum Beispiel C, C++, Perl oder COBOL mit ExplorViz zu instrumentieren. 10 Kapitel 3 Monitoring Android Applikationen Im folgenden Kapitel werden wir verschiedene Möglichkeiten aufführen um unser Ziel, das Monitoring von Android Anwendungen, zu erreichen. Zuerst betrachten wir dafür Techniken zum Instrumentieren von Android Anwendungen. Anschließend werden wir uns für eine Anwendung entscheiden. Android unterstützt nicht das Modifizieren des Bytecodes zur Laufzeit. Weiterhin erschwert die Struktur der dex-Datei die direkte Instrumentierung. Jedoch gibt es zahlreiche Ansätze, die mit einer zwischenform von einer dex-Datei arbeiten. Dazu betrachten wir zunächst den Build-Prozess (Abbildung 3.1) zum Erstellen einer APK. Abbildung 3.1. Vereinfachte Darstellung des Build-Prozess zum Instrumentieren Die Applikation ist in Java geschrieben und liegt als unkompilierter Sourcecode vor. 11 3. Monitoring Android Applikationen Der Java-Quellcode wird anschließend mit dem Java Compiler (javac) in Java-Bytecode übersetzt. Um das Programm auf die Architektur von Android anzupassen, wird dieser anschließend mit dem dx-tool in die Dalvik executable übersetzt. Da es sich beim instrumentierten Java-Code um korrekte Java-Ausdrücke handelt, ist es möglich die Instrumentierung vor dem Übersetzen in das Dex-Format, mit Java-Klassen durchzuführen. Dafür kann der Java-Quellcode vor dem ersten Kompelierungsschritt verwendet werden. Ein anderer Ansatz wäre erst die Übersetzung in Java-Bytecode vorzunehmen, und anschließend mit diesem die Instrumentierung durchzuführen. Wir haben bereits im Abschnitt 2.3 den Ansatz der aspektorientierten Programmierung kennengelernt. Die dazu vorgestellte Java-Erweiterung AspektJ kann sowohl als JavaCompiler angewendet werden und Sourcecode und Aspekte zur Compile-Zeit übersetzen und einweben, als auch mit Java-Bytecode arbeiten. Im Folgenden stellen wir eine Auswahl an Techniken und Frameworks für das Instrumentieren für Java vor. 3.1. Manuelle Instrumentierung Eine Möglichkeit Java-Sourecode zu instrumentieren ist es manuell Änderungen vorzunehmen. Der Entwickler muss per Hand neuen Programmcode in den Sourcecode einfügen. Ein Nachteil ist, dass häufig eine Vielzahl an Änderungen vorgenommen werden muss und diese Änderungen direkt in den Source-Dateien vorgenommen wird. Dies kann recht unübersichtlich werden, da die eigentliche Logik des Programmes mit dem Monitoring-Advice vermischt wird. Eine Fehlerquelle könnte hier sein, dass nötige Änderungen übersehen werden. Außerdem verschlechtert dies auch die Wartbarkeit des Quellcodes. 3.2. Instrumentation-Klasse Android bietet seit dem API Level 1 eine Instrumentation1 Klasse an. Diese wird im AndroidManifest festgelegt und dient als eine Basisklasse für das Monitoring von Interaktionen der Anwendung mit dem System. Das Instrumentierungs-Objekt wird vor dem Start der Anwendung instanziiert. Jedoch ist diese Klasse nur für das Schreiben und Testen von entwickelten Android Applikationen gedacht und bietet für unsere Ziele nicht genügen Funktionalität, wie zum Beispiel reguläre Ausdrücke, wie es unter anderem bei dem Pointcuts mit AspectJ möglich ist. 1 https://developer.android.com/reference/android/app/Instrumentation.html 12 3.3. BCEL 3.3. BCEL BCEL 2 ist ein Akronym für Byte Code Engineering Library. Das Projekt beinhaltet eine API zum Modifizieren von Java-Bytecode. Es wird in unterschiedlichen Projekten, unter anderem auch in dem AspectJ-Projekt, verwendet. Hat der Entwickler nur die APK und keinen Zugriff auf den Java-Sourcecode, sind die oben beschrieben Ansätze nicht ohne weiteres möglich. Deshalb stellten wir im Folgenden einige Technologien zum Arbeiten mit APKs und der darin enthaltenden classes.dex. 3.4. Soot Das Framework Soot3 , kann zum Analysieren und Instrumentieren von Java- und AndroidProgrammen verwendet werden. Soot akzeptiert als Ein- und Ausgabe unter anderem .java, .dex und APK Dateien, indem es intern alles zu Jimple-Zwischendarstellungen übersetzt. Jimple ist eine vereinfachte Java Sourcecode Version mit maximal drei typisierten lokalen Variablen pro Codezeile. Aspekte werden nicht in Java-Syntax, sondern in Jimple-Syntax definiert. 3.5. AspectBench Compiler Der AspectBench Compiler (abc)4 ist eine Neuentwicklung des AspectJ Compilers (ajc). Anders als der ajc unterstützt der abc auch das AOP für Android-Anwendungen [Arzt u. a. 2013]. Mit dem AspectBench Compiler können APK ohne Zwischenschritt direkt instrumentiert werden. Dazu wird für das Back-Endintern das Soot Framework verwendet. Dies übersetzt die dex.classes in eine Zwischenform und führt darauf die Instrumentierung aus. Für die Definition von Aspekten wird wie bei AspectJ das Dateiformat .aj verwendet. Anschließend wird mit Soot wieder eine APK erstellt. Allerdings ist die Entwicklung eingestellt und das letzte offizielle Release wurde im April 2008 veröffentlicht. Deshalb unterstützt der AspectBench Compiler Java nur bis zu der Version 5 und unter anderem nicht die Annotation-Syntax für das Schreiben von Aspekten. 2 https://commons.apache.org/proper/commons-bcel 3 https://sable.github.io/soot 4 www.sable.mcgill.ca/abc 13 3. Monitoring Android Applikationen Im Folgenden stellen wir noch ein Programm vor, welches dex-Dateien in Java-Klassen dekompilieren kann. Es können anschließend Techniken zum Instrumentieren von JavaBytecode verwendet werden (siehe Abbildung 3.1). 3.6. dex2jar Das Werkzeug dex2jar5 nimmt die dex-Datei als Eingabe und dekompiliert sie zu einer JAR. Das dex2jar Programm wurde unter anderem in [Bartel u. a. 2012] und [El-Harake u. a. 2014] verwendet, um den Code so zu verändern, sodass Werbung innerhalb der Applikation blockiert wird. Allerdings besteht ein bedeutender Unterschied zwischen dem Register-basierten Dalvik VM und der Stack-basierten Java VM und das Dekompilieren funktioniert nicht immer fehlerfrei [El-Harake u. a. 2014]. 3.7. jadx Das Priogramm jadx6 ist ein weiteres Dekompilierungs-Tool. Es lässt sich sowohl über die Kommandozeile, als auch über eine GUI bedienen. Anders als dex2jar, unterstützt jadx auch das Dekompilieren von APKs in Java-Source Dateien. Das dekompilieren von Ressourcen funktioniert jedoch nur rudimentär und es wird ein weiteres Werkzeug für diese Aufgabe empfohlen. 3.8. APKtool Das APKtool 7 ist ein Werkzeug zum Reverse Engineering von Android APKs. Mit dem APKtool ist es möglich Resourcen und das AndroidManifest zu dekompilieren. Außerdem unterstützt es das Dekompilieren von dex-Dateien zu smali code 1 , welches eine extra für das Dekompilieren von Android entwickelte Sprache ist. Der dekompilierte smali code kann modifiziert und anschließend mit dem APKtool wieder in eine APK packen. 5 https://github.com/pxb1988/dex2jar 6 https://github.com/skylot/jadx 7 https://ibotpeaches.github.io/Apktool 1 https://github.com/JesusFreke/smali 14 3.9. Auswahl der Instrumentierungs-Technik 3.9. Auswahl der Instrumentierungs-Technik Die obige Auswahl soll zeigen, dass es einige Werkzeuge und Ansätze zum Instrumentieren von Android gibt. Wir entscheiden uns aufgrund der Vielfältigkeit und einfachen Handhabung für AspectJ. Ein wichtiger Punkt dabei ist auch, dass ExplorViz bereits AspectJ für die Instrumentierung verwendet. Für das Dekompilieren wählen wir bewusst kein konkretes Werkzeug aus, da das Erzeugen der Java-Klassen nicht immer fehlerfrei ist. In unterschiedlichen Fällen kann es sinnvoll sein eine Dekompilierungs-Technik der anderen vorzuziehen. Wir zeigen im Laufe dieser Arbeit, wie die benötigten Schritte mit Jadx und dem APKtool funktionieren. 15 Kapitel 4 Monitoring in ExplorViz Im folgenden Kapitel werden wir den aktuellen Stand für ExplorViz und insbesondere die Monitoring-Komponente erläutern. Darauf aufbauend werden wir anschließend einen Entwurf für eine Monitoring-Komponente entwickeln, die das Monitoring von Android unterstützt. 4.1. Aktueller Stand im ExplorViz Das Monitoring und Visualisierungstool ExplorViz besteht, wie in (Abbildung 4.1) beschrieben, aus drei Komponenten: Monitoring, Analyse, Webserver. In der MonitoringKomponente werden die Monitoring-Records erstellt. Dabei werden je nach verwendetem Aspekt verschiedene Records berücksichtigt. Abbildung 4.1. Komponentendiagramm für ExplorViz aus [Fittkau 2015] Die Monitoring-Records werden zu der Analyse-Komponente auf dem Trace Processing 17 4. Monitoring in ExplorViz Server gesendet, welche die Traces vorbearbeitet, um eine Überbeanspruchung der AnalyseKomponente zu verhindern. Anschließend werden die Traces zur Analyse-Komponente an den Visualization Server geschickt. Diese ist Teil des Visualization Providers, welcher innerhalb eines Application Servers läuft. Das visualisierte Modell wird auf Anfrage zum Client, beziehungsweise einem Web Browser gesendet (S. 161 [Fittkau 2015]). Monitor-Komponente Für das Monitoring von Android Anwendungen betrachten wir die Monitoring-Komponente genauer. Für das Monitoring von Methodenaufrufen stellt ExplorViz derzeit folgende Records zur Verfügung: BeforeOperationEventRecord AfterFailedOperationEventRecord AfterOperationEventRecord BeforeConstructorEventRecord AfterConstructorEventRecord AfterFailedConstructorEventRecord BeforeStaticOperationEventRecord AfterFailedStaticOperationEventRecord AfterStaticOperationEventRecord Diese Records ermöglichen es Zustände vor, nach, und nachdem eine Exception geworfen wurde festzuhalten. Es wird dabei zwischen unterschiedlichen Methoden-Arten unterschieden. Mit OperationEventRecord werden die gewöhnlichen Methoden bezeichnet. Eine weitere Unterscheidung wird bei den Konstruktoren (ConstructorEventRecord) und statischen Methoden (StaticOperationEventRecord) gemacht. In ExplorViz werden sie in der Klasse AbstractAspect als Aspekte mit angeben. Diese Klasse ist die Basis-Klasse für das Monitoring von Methodenaufrufen. Hier werden die Pointcuts angegeben und die einzufügenden Aspekte. Es handelt sich um eine abstrakte Klasse. Die Advices verwenden den Around-Typ und rufen vor dem eigentlichen Ausführen der Methode die Methode createEventRecords() auf. Hier werden zunächst Daten für einen 18 4.1. Aktueller Stand im ExplorViz BeforeRecord gesammelt und in einen ThreadLocalByteBuffer gespeichert, anschließend wird versucht die eigentliche Methode auszuführen. Wirft diese eine Exception, so wird diese gefangen und es werden Daten für den AfterFailedRecord gesammelt und die Exception anschließend geworfen. Wenn die Methode korrekt ausgeführt wurde, dann werden anschließend Daten für den AfterRecord in den ByteBuffer geschrieben. ExplorViz verwendet für das einweben der Aspekte den load-time weaving Ansatz. Dafür wird die abstrakte Klasse DistributedMonitoringAspect verwendet, welche von der AbstractAspect erbt. Da AspectJ nur Aspekte aus konkreten Klassen einwebt, wird ein Konfigurationsdatei aop.xml verwendet. Diese erstellt eine konkrete Klasse mit Aspekten, indem sie die DistributedMonitoringAspect Klasse erweitert und die Pointcuts definiert. Zur Laufzeit werden die Aspekte dann beim Laden der Klasse eingewoben. Dieser Ansatz hat den Vorteil, dass man in der aop.xml die Pointcuts und Aspekte variabel an die gegeben Anforderungen an das Monitoring anpassen kann. So können zum Beispiel auch andere Klassen als DistributedMonitoringAspect als Aspekt verwendet werden. Abbildung 4.2. Monitor-Komponenten entnommen aus [Fittkau 2015] Die Abbildung 4.2 gibt einen Überblick über die Monitoring-Komponente. Die gesammelten Daten werden wie oben in einen ByteBuffer gespeichert und anschließend an den Monitoring Controller geschickt. Zur Synchronisation werden die ByteBuffer in einen Ring Buffer zwischengespeichert. Der Monitoring Writer sendet die ByteBuffers über eine TCPVerbindung an die Analyse-Komponente. Der Monitoring Write arbeitet in einen anderem Thread und sendet die ByteBuffer. Dies kann aus zwei Gründen geschehen. Entweder ist der ByteBuffer voll, oder wenn der Tracecounter wieder auf null ist. Das heißt, wenn bei einer Abfolge von aufeinander aufbauenden Methodenaufrufen die initiale Methode beendet wurde. Neben den gesammelte Informationen über die Methoden, i.e. Methoden, statische 19 4. Monitoring in ExplorViz Methoden und Konstruktoren werden noch weitere Daten an die Analyse-Komponente gesendet. HostApplicationMetaDataRecord Die MetaDaten werden einmalig zum Beginn als initialer ByteBuffer gesendet und enthalten Informationen über den Systemnamen, die IP-Adresse, den Hostnamen, die Applikations-ID und die Sprache. Diese werden in der Visualisierung der Landschaftsperspektive später angezeigt. Diese Daten können in der explorviz.live_trace_processing.default.properties angeben werden. Hier werden auch allgemeine Einstellungen, wie die IP-Adresse des Servers für die Analyse- und Visualisierungs-Komponente angegben. SystemMonitoringRecord Der SystemMonitoringRecord sammelt Information über die CPU-Auslastung und den Speicherverbrauch der Anwendung. Dafür wird die Java Klasse com.sun.management.OperatingSystemMXBean verwendet [Fittkau 2015]. Android in ExplorViz In ExplorViz sind bereits Ansätze für die Instrumentierung von Android vorhanden. Florian Fittkau hatte 2013 im Rahmen seiner Dissertation für die Evaluation von ExplorViz eine Android Applikation mit ExplorViz instrumentiert (S.191 [Fittkau 2015]). Dafür wurde ein androidMonitoring-Flag eingeführt, welches unterscheiden soll, ob es sich bei dem zu instrumentierenden Programm um ein Java oder Android Applikation handelt. ExplorViz baut initial direkt aus dem Main-Thread eine TCP-Verbindung mit der AnalyseKomponente aufbaut. Unter Android ist dies aus Performancegründen nicht erlaubt, da Netzwerkkommunikation langwierig sein kann und das System zwischenzeitlich nicht mehr reaktiv wäre. 20 4.2. Entwurf 4.2. Entwurf Im Verlauf dieser Arbeit beziehen wir uns auf die Monitoring-Komponente. Da die Android Anwendungen in Java geschrieben sind, können die Records hier übernommen werden und müssen nicht extra angepasst werden. Deshalb reicht es aus sicherzustellen, dass die erstellten Monitor-Records über eine TCP-Verbindung an die Analyse-Komponente geschickt werden. Von dort aus werden sie genauso wie die Records von Java-Programmen behandelt. Abbildung 4.3. Deployment-Diagramm für Android-Monitoring in ExplorViz Abbildung 4.3 zeigt wie das spätere Deployment für das Android-Monitoring in ExplorViz aussehen wird. Der Sourcecode soll zusammen mit der ExplorViz-Komponente in einer APK kompiliert werden. Diese wird anschließend auf dem mobilen Endgerät installiert und zum Laufen gebracht. Die eingewobenen Advices sammeln Informationen über das System und senden diese an die Analyse-Komponente. Kompatibilität mit Android Zum Erstellen der Monitoring-Komponente sind einige Punkte zu beachten. Android basiert zwar auf Java, dennoch werden nicht alle Java APIs unterstützt. Zunächst muss einmal überprüft werden, welche Libraries nicht unter Android funktionieren. Diese müssen anschließend entfernt und verwendete Methoden gegebenenfalls mit Alternativen ergänzt werden. Weiterhin wird die Monitoring-Komponente derzeit mit dem Java-Compiler kompiliert. Dies ist bei der Verwendung von Aspekten in einer Library in Verbindung mit dem post-compile weaving nicht möglich. Wenn man versuchen würde dennoch solch Aspekte einzuweben, kommt es zur Laufzeit zu einer MethodNotFoundException: aspectOf(). Dieses Problem kann gelöst werden, wenn anstatt des Java-Compilers der AspectJ Compiler 21 4. Monitoring in ExplorViz verwendet wird. Dabei wird die statische aspectOf Methode mit in die kompilierte Library gepackt. Auch muss darauf geachtet werden, dass gerade ältere Android Versionen nur bis zu der Java Version 7 kompatible sind. Dazu kann das Ant-Build-Skript, welches ExplorViz derzeit verwendet, angepasst werden. Bei größeren Apps kann es zu Problemen mit der Anzahl der referenzierten Methoden kommen. Diese sind für eine einzelne dex-Datei auf 65.536 Stück begrenzt. Dazu zählen auch die Methoden aus den Frameworks und Bibliotheken, sowie die durch die Aspekte eingewobenen Methoden. Allerdings ist es möglich den Programmcode auf mehrere dexDateien aufzuteilen. 22 Kapitel 5 Implementierung In diesem Kapitel wirdf die Vorgehensweise der Instrumentierung und die Implementierung der ExplorViz-Komponente für das Monitoring von Android Applikationen beschrieben. Zunächst werden wir auf die Instrumentierung von Android Anwendungen eingehen. Anschließend behandeln wir den Sonderfall der Instrumentierung von APKs. Danach werden wir auf die Änderungen der Monitoring-Komponente von ExplorViz eingehen. 5.1. Sourcecode Instrumentierung Wenn der Entwickler den Sourcecode der zu instrumentierenden Applikation hat, ist es möglich diese während des Build-Prozesses zu instrumentieren. Dabei können sowohl das compile-time weaving, als auch das post-compile weaving verwendet werden. Wie bereits in Abschnitt 3.9 angekündigt, werden wir AspectJ zur Instrumentierung verwenden. Weiterhin verwenden wir einen Ansatz mit post-compile weaving. Dies hat den Vorteil, dass der eigentliche Java-Compiler weiter verwendet werden kann und wir nur einen zusätzlichen Schritt in den Build-Prozess mit einbauen müssen (siehe Abbildung 3.1). 5.1.1. Build-Skript Google empfiehlt seit 2013 Gradle als Build-Tool für Android zu verwenden. Im Folgenden werden wir ein Gradle-Plugin vorstellen, welches wir dazu verwenden in den Build-Prozess noch einen weiteren Task einzufügen. Nach dem Kompilieren des Java-Sourcecodes werden definierte Aspekte mit dem AspectJ compiler eingewoben. Anschließend wird der Build-Prozess wie gewohnt vorgeführt. Dazu fügen wir zunächst die ExplorViz-Monitoring-Library in das Projekt als ein neues Modul ein. Um das Plugin nutzen zu können, müssen wir zunächst Gradle sagen, woher er das Plugin beziehen soll. Dazu geben wir in Listing 5.1 den Klassenpfad des Plugins in der build.gradle im Hauptprojekt-Ordner an. Dabei ist darauf zu achten, dass die richtige Gradle-Version installiert ist. Um das Plugin verwenden zu können, wird eine Gradle-Version von Gradle 2.1.3 oder höher benötigt. 23 5. Implementierung Listing 5.1. Klassenpfad für das Gradle-Plugin 1 buildscript { 2 repositories { "Test" 3 jcenter() 4 } 5 dependencies { 6 classpath ’com.android.tools.build:gradle:2.1.3’ 7 8 //Klassenpfad: Gradle-Plugin 9 classpath ’com.hujiang.aspectjx:gradle-android-plugin-aspectjx:1.0.7’ 10 } 11 } Um das Plugin anschließend in den Build-Prozess zu integrieren, muss es in dem GradleSkript des zu instrumentierenden Android-Projektes angeben werden. Anschließend geben wir noch an, dass wir die zuvor eingebundene Monitoring-Library mit kompilieren wollen (Listing 5.2). Listing 5.2. Klassenpfad für das Gradle-Plugin 1 apply plugin: ’android-aspectjx’ 2 3 ... 4 5 dependencies { 6 compile project(":explorviz-monitoring-android") 7 } Das Plugin durchsucht das Projekt nach Klassen, die Aspekte definiert haben, und versucht diese auf alle .class-Dateien anzuwenden. Es ist nicht immer sinnvoll jede Klasse zu instrumentieren. So möchte man zum Beispiel vielleicht die externen Programmbibliotheken nicht instrumentieren. Es ist möglich einzelne Bibliotheken von der Instrumentierung auszuschließen oder auch wie in Abschnitt 5.3 beschrieben generell alle .jar-Dateien. Listing 5.3. Ausschließen von jars 1 aspectjx { 2 excludeJarFilter ’.jar’ 3 } Möchte der Entwickler bestimmte .jar-Dateien mit instrumentieren, so können diese mit includeJarFilter explizit angeben werden. 24 5.2. APK Instrumentierung 5.2. APK Instrumentierung Steht der Sourcecode zur Instrumentierung nicht zu Verfügung und der Entwickler hat nur eine APK, ist es dennoch möglich diese zu Instrumentieren. Dazu dekompilieren wir die APK, beziehungsweise die dex-Datei daraus zu Java Sourcecode. Anschließend können wir den Sourcecode instrumentieren und die APK erstellen. 5.2.1. Reverse Engineering Im Kapitel 3 wurden einige Tools zum Reverse Engineering von APKs vorgestellt. Dazu verwenden wir im Folgenden die Programme jadx zum Dekompilieren der dex-Datei und das APKtool zum Dekompilieren der Ressourcen und des AndroidManifest. Mit jadx lassen sich APKs direkt bearbeiten. Die dex-Datei wird dabei herausextrahiert und in Java-Sourcecode dekompiliert. Ähnlich verfährt auch das APK-Tool mit den Metadaten. Die übersetzten Daten können anschließend in ein neu erstelltes Gradle-Projekt eingebunden werden. 5.2.2. Probleme Durch die unterschiedlichen Strukturen von Java-Bytecode und Dalvik-Bytecode lassen sich nicht immer alle Klassen vollständig korrekt rekonstruieren. Die Dekompiler sind anfällig und der zurückübersetzte Code muss gegebenenfalls angepasst werden. Erschwert wird dieser Vorgang durch den vorangegangen Einsatz von ProGuard um den Programmcode zu verschleiern. Bezeichnungen von Methoden, Parametern, Variablen, Klassen und Packages können dabei umbenannt werden. Ein anschließendes Monitoring mit ExplorViz wäre dadurch sinnlos. 5.3. Android-Monitoring in ExplorViz In diesem Abschnitt werden wir uns mit dem Erstellen der Monitoring-Komponente für Android beschäftigen. Als Grundlage dient die Monitoring-Komponente von ExplorViz. Zuerst strukturieren wir diese so, dass sie kompatibel zu Android ist. Anschließend beschäftigen wir uns mit dem System-Monitoring, i.e. das Messen der CPU-Auslastung und dem Arbeitsspeicherverbrauch des Programmes. Zum Schluss behandeln wir noch variable Pointcuts, um dem Entwickler die Möglichkeit zu geben eigene Pointcuts für das Monitoring zu definieren. 25 5. Implementierung 5.4. Kompatibilität mit Android In der Monitoring-Komponente von ExplorViz gibt es einige Klassen und Bibliotheken, die APIs verwenden, welche nicht mit Android Kompatible 1 sind: ActiveMQProbe, javax.jms JAXWSProbe, javax.xml JAXWSProbeAdder, javax.xml, javax.jws SystemMonitorProbe, com.sun.management.OperatingSystemMXBean Bei den ersten drei Klassen handelt es sich um Aspekte, welche nicht für das Instrumentieren der Methodenaufrufe benötigt werden. Diese können also beim Erstellen der ExplorViz-Monitoring-Library weggelassen werden. Die letzte Klasse ist für das Erstellen der SystemMonitorRecords zuständig. Systemmonitoring Eine Alternative für den Arbeitsspeicherverbrauch wäre über die Runtime den freien und den gesamten Speicher abzufragen: Runtime.getRuntime().freeMemory() Runtime.getRuntime().maxMemory() Für die CPU-Auslastung nutzen wir, dass Android auf den Linux Kernel basiert. Wie unter Linux ist es möglich, Informationen über die CPU-Auslastung aus der /proc/stat Datei auszulesen. Dabei wird die Auslastung für das gesamte System betrachtet, also nicht nur für die instrumentierte Applikation, sondern auch für die im Hintergrund laufenden Prozesse. Nicht kompatible Programmbibliotheken Folgende Klassen verwenden mit dem LMAX Disruptor ein Library, welche nicht mit Android kompatibel ist: ByteBufferEvent, com.lmax.disruptor MonitoringController, com.lmax.disruptor ThreadSleepWaitingStrategy, com.lmax.disruptor TCPWriter, com.lmax.disruptor Das LMAX Disruptor Framework ist ein zentraler Punkt in der Verarbeitung und das Senden von Records in der Monitoring-Komponente. Es wird verwendet um den RingBuffer zu implementieren. Die Library verwendet die Klasse sun.misc.Unsafe, welche in Android nicht zur Verfügung steht. Allerdings hat sich gezeigt, dass der RingBuffer trotzdem unter Android funktioniert, da nicht auf die Unsafe-Klasse zugegriffen wird. 1 https://developer.android.com/reference/packages.html 26 5.4. Kompatibilität mit Android Build-Prozess Um die Monitoring-Komponente für Android bereit zu stellen, muss sie zum einen mit dem AspectJ Compiler gebaut werden und zum anderen darf sie nicht mit einer höheren Version als Java 7 kompiliert werden. Dazu passen wir das Build-Skript für ExplorViz an. ExplorViz verwendet Apache Ant. Wir erweitern die build.xml um weitere Tasks, wie in Listing 5.4 zu sehen. Der Task build-android-monitoring (Zeile 1-4) ist der Haupttask, welcher die Abhängigkeiten der Monitoring-Komponente beschreibt. In Zeile 13-15 wird definiert, dass die Klassen der Monitoring-Komponente mit dem AspectJ Compiler und einen Kompilerlevel von Java 7 kompiliert werden soll. Zeile 27 schließt die nicht kompatiblen Klassen aus der Jar aus. Das Unterprojekt common, welches Klassen für die Monitor-Komponente bereitstellt, muss ebenfalls mit der Java Version 7 kompiliert werden. Da aber in dem Projekt keine Aspekte sind, reicht der normale Java-Compiler aus. 27 5. Implementierung Listing 5.4. Auszug aus dem build.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <target name="build-android-monitoring" depends="clean,compile-ajc,monitoring-Android-jar,test-ajc" description="Compiles and packages the Jar for Android-Monitoring"> </target> <target name="compile-ajc" depends="build-all-common"> <mkdir dir="${build.dir}" /> <copy todir="${build.dir}"> <fileset dir="${common-monitoring.dir}/dist"/> </copy> <iajc srcdir="${src.dir}" destdir="${build.dir}" classpathref="classpath" source="1.7" target="1.7" debug="true" /> </target> <target name="monitoring-Android-jar"> <mkdir dir="${jar.dir}"/> <jar destfile="${jar.dir}/explorviz-monitoring-android.jar"> <manifest> <attribute name="Class-Path" value="."/> <attribute name="Can-Redefine-Classes" value="true"/> <attribute name="Can-Retransform-Classe" value="true"/> </manifest> <fileset dir="${build.dir}" excludes="*common*.jar, **/ActiveMQProbe.class, **/ JAXWSProbe*.class" /> 28 29 <fileset dir="lib" includes="*LICENSE*" /> <fileset dir="${src.dir}" includes="META-INF/explorviz.live_trace_processing. default.properties" /> 30 <fileset dir="${src.dir}" includes="**/Pointcuts.java" /> 31 32 <zipfileset excludes="META-INF/*.SF" src="${build.dir}/explorviz-common.jar"/> 33 <zipfileset excludes="META-INF/*.SF" src="lib/slf4j-api-1.7.5.jar"/> 34 <zipfileset excludes="META-INF/*.SF" src="lib/disruptor-3.3.0.jar"/> 35 </jar> 36 </target> 28 5.5. Aspekte Listing 5.5. Pointcuts.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package explorviz.live_trace_processing.probe; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; // concrete Aspect for compile time weaving @Aspect public class Pointcuts extends AbstractAspect { @Override @Pointcut("execution(* *..*(..)) && within(*)") public void monitoredOperation() {} @Override @Pointcut("execution(*..*.new(..)) && within(*)") public void monitoredConstructor() {} } Netzwerkkommunikation Die Monitoring-Komponente sendet die Records über eine TCP-Verbindung an die Analyse-Komponente. Damit dies möglich ist braucht die Applikation die Berechtigung Netzwerkoperationen durchzuführen. Diese Berechtigung kann in dem AndroidManifest gesetzt werden. Außerdem muss die IP-Adresse des Servers in der explorviz.live_trace_processing.default.properties im META-INF Ordner angeben werden. Beim Android Emulator, welcher per USB über die Android Debug Bridge (ADB) angeschlossen ist, ist die IP-Adresse des localhost 10.0.2.2. 5.5. Aspekte ExpolorViz verwendet für das load-time weaving Klassen für die Aspekte, welche zunächst abstrakt sind. Hinzu kommt, dass die Pointcuts erst in der Konfigurationsdatei konkretisiert werden. Dies ist beim post-compile weaving nicht möglich. Deshalb brauchen wir eine konkrete Klasse mit Pointcuts, die von der Basisklasse AbstractAspect abgeleitet wird. AbstractAspect enthält bereits die Advices und Teile der Pointcuts. So wird generell schon einmal zwischen Methoden und statischen Methoden unterschieden. Auch wird die Monitoring-Komponente ausgeschlossen, damit sich die Aspekte nicht rekursiv selbst instrumentieren. Und wir müssen nur die Pointcuts für monitoredOperation und monitoredConstructor definieren. Listing 5.5 ist die implementierte Klasse dazu. Generell werden alle Methoden und alle Konstruktoren instrumentiert. 29 5. Implementierung 5.6. Variable Pointcuts Die Pointcuts im vorherigen Abschnitt sind fest in der Monitoring Library kompiliert und so nicht mehr nachträglich änderbar. Damit man sich eigen Pointcuts definieren kann, beziehungsweise das Instrumentieren auf einige Packages beschränken kann, muss man sich eine eigen Klasse schreiben, welche von AbstractAspect erbt. Dazu geben wir die unkompilierten Pointcuts.java in der Library mit. Der Entwickler kann diese aus der Library entnehmen und nach Bedarf anpassen. Dabei sind zwei Punkte zu beachten. Zum einen muss der Pfad, in der die Klasse liegt, zum sourcepath des Compilers gehören. Außerdem muss das Package, in dem die Klasse befindet durch den neu definierten Pointcut ausgeschlossen werden, da sich der Aspekt ansonsten selbst instrumentiert. Zum Schluss muss die kompilierte Pointcuts.class aus der Library gelöscht werden, da sonst der Aspekt ebenfalls mit eingewoben wird. 30 Kapitel 6 Evaluation Wir wollen unsere Implementierung zum einen auf Funktionalität überprüfen. In der Landschaftsperspektive soll Auskunft über den Namen und den Resourceverbrauch der Applikation gegeben werden. In der Applikationsicht sollen die Klassen in Ihren Packages, sowie die Kommunikation zwischen den Klassen dargestellt werden. Zum anderen wird unsere Implementierung auf die Usability evaluiert. Es soll einem Entwickler möglich sein mit der Monitoring-Komponente seine Applikation ohne viel Aufwand zu instrumentieren und mit ExplorViz visuell darzustellen. Versuchsaufbau Zum Test der Monitoring-Komponente verwenden wir eine App, die 2013 von Studenten im Rahmen des Softwareprojektes an der Christian-Albrechts-Universität zu Kiel geschrieben wurde. Der Sourcecode ist vorhanden und wird für die Instrumentierung verwendet. Die Zielversion der Applikation ist mit der API 19 relativ alt. Zum Test wird der Android Emulator von Android Studio mit einer Android Version, die der API 19 entspricht, verwendet. Das Ergebnis wird ausgewertet und mit dem Sourcecode verglichen. Instrumentierung mit dem Sourcecode Das Projekt wurde mit dem Build-Tool Ant erstellt. Zum Instrumentieren auf Sourcecodebasis laden wir das Projekt als erstes in Android Studio und importieren es als GradleProjekt. Anschließend laden wir die Monitoring-Komponente als Modul in das Projekt und instrumentieren die Applikation, wie in Abschnitt 5.1 beschrieben. Auswertung Das Importieren in ein Gradle-Projekt hat funktioniert. Die anschließende Instrumentierung konnte erfolgreich durchgeführt werden und die erstellte APK auf den Emulator installiert werden. Es ist jedoch zu beobachten, dass der ExplorViz-Server vor der App gestartet 31 6. Evaluation werden muss. Geschieht dies nicht, startet die Applikation zwar, reagiert aber auf keine Eingaben mehr. Es ist zu vermuten, dass die Applikation in diesem Zustand versucht sich wiederholend mit der IP zu verbinden. Wurde der Server zuvor gestartet, wird nach kurzer Zeit die Landschaftsperspektive, wie in Abbildung 6.1 visualisiert. Abbildung 6.1. Babsi in der Landschaftsperspektive Es wird korrekt die Babsi Applikation angezeigt. Beim System-Monitoring fällt auf, dass der Total RAM mit 0GB angegeben ist. Diese Kennzahl spiegelt nicht den gesamten Arbeitsspeicher des Gerätes wieder, sondern gibt nur den Speicher an, welcher der Android Anwendung maximal zugewiesen werden kann. Diese Grenze ist durch das Android System gegeben. Diese liegt bei dem Emulator bei 32 Megabyte. Dies ist deutlich unter einen Gigabyte und es ist anzunehmen, dass hier abgerundet wurde. In der Applikationsperspektive(Abbildung 6.2) werden die einzelnen Packages und die Klassen richtig zugeordnet. Man erkennt die Kommunikation unter den Klassen und es lassen sich auch die Reaktionszeiten ablesen. Die Visualisierung reagiert, nach kurzer Verzögerung auf die Eingaben, welche auf den Emulator vorgenommen wurden. 32 Abbildung 6.2. Babsi in der Applikationsperspektive Zur Usability lässt sich feststellen, dass ein Monitoring einer eigenen Android App ohne zusätzlichen Programmieraufwand möglich ist. Es wird im Sinne des Separation of Concerns nicht direkt in den Sourcecode eingegriffen und die Aspekte sind klar vom Code der eigentlichen Anwendung getrennt. Es bedarf lediglich einer Anpassung des GradleSkriptes. Auch wurde die Software mit älteren Android Versionen getestet (Android 4.4, API 19). 33 Kapitel 7 Verwandte Arbeiten In diesem Kapitel werden wir einige verwandte Arbeiten vorstellen. Der Fokus liegt dabei auf der Instrumentierung von Android. Ein weiterer Aspekt ist das Monitoring des Ressourcenverbrauches. 7.1. Kieker Monitoring Framework Kieker1 ist ein System zum Monitoring und zur dynamischen Softwareanalyse von Software zur Laufzeit. Es besteht im Wesentlichen aus den zwei Komponenten Kieker.Monitoring und Kieker.Analysis. Die Monitoringkomponente stellt Klassen und Methoden für eine Instrumentierung und das Erzeugen von Records zu Verfügung. Die generierten Records können an die Analyse Komponente übergeben werden und dort weiter analysiert werden. Kieker basiert auf Java und bietet nativ die Instrumentierung für Java-Anwendung an. Das Monitoring von Android wird derzeit nicht unterstützt. Jedoch wäre ein ähnlicher Ansatz, wie der der in dieser Arbeit vorgestellten Sourcecode-Instrumentierung, denkbar. Um eine Schnittstelle für andere Sprache anzubieten, wurde die Kieker Data Bridge (DKB) entwickelt. Die KDB erlaubt es andere Programmiersprachen in Kieker zu implementieren. 7.2. SPASS-meter SPASS-meter2 ist ein Monitoring-Framework für das Messen des Ressourcenverbrauchs von Java-Programmen. Es erlaubt das Monitoring von Android-Anwendungen, indem es den Build-Prozess so verändert, dass die JAR-Datei instrumentiert wird, bevor diese zum Dalvik Executable-Format kompiliert wird. Dazu wird die Byte Code Engineering Library (Apache Commons BCEL)verwendet, welche das Lesen und Verändern von Java-Bytecode ermöglicht. Mit Annotationen im Sourcecode oder durch ein XML-Datei können die Bereiche, welche überwacht werden sollen, definiert werden. Die Weiterentwicklung im Bereich der Android Instrumentierung ist derzeit eingestellt. 1 http://kieker-monitoring.net 2 http://sse.uni-hildesheim.de/forschung/projekte/spass-meter 35 7. Verwandte Arbeiten 7.3. Android Monitor Android Monitor3 ist ein Werkzeug von Android Studio. Es lassen sich zuvor definierte Logs auslesen und die aktuelle Arbeitsspeicher-, CPU-, GPU- und Netzwerkauslastung anzeigen. Weiterhin ist es möglich Methoden-Traces aufzuzeichnen, um diese später im Kontext des Ressourcenverbrauches zu analysieren. 3 https://developer.android.com/studio/profile/android-monitor.html 36 Kapitel 8 Fazit und Ausblick In diesem Kapitel werden wir die Implementierung und die Auswertung noch einmal zusammenfassen. Im Ausblick werden Vorschläge für zukünftige Arbeiten gegeben. 8.1. Fazit Im Rahmen der Bachelorarbeit haben wir uns mit dem Monitoring und der Visualiserung mit ExplorViz von Android Applikationen beschäftigt. Dabei haben wir primär den Fall betrachtet, dass ein Entwickler seine Applikation über den Sourcecode instrumentieren möchte. Aufgrund der einfachen Handhabung und der Tatsache, dass ExplorViz bereits AspectJ verwendet, haben wir uns für diesen aspektorientierten Ansatz entschieden. Das Einweben der Aspekte geschieht mit Hilfe eines Gradle-Plugins. Wir haben die MonitoringKomponente von ExplorViz für Android angepasst. Dazu haben wir nicht kompatible Programmteile entfernt und teilweise ersetzt. Auch haben wir das Build-Skript angepasst. Im Ansatz haben wir noch den Fall betrachtet, dass der Entwickler nur die APK der Android App zur Verfügung hat. Wir haben einen möglichen Weg aufgezeigt, wie man APKs mit Hilfe des Dekompilierens instrumentieren kann. Die Evaluation am Schluss hat gezeigt, dass die Instrumentation von Android Sourcecode mit ExplorViz möglich ist. Die Monitoring-Library kann auf einem einfachen Weg in ein aktuelles Projekt integriert werden und so das Monitoring von ExplorViz nutzen. 8.2. Ausblick In dieser Arbeit wurde das Monitoring der grundlegenden Methoden behandelt. Es können noch weitere Aspekte, welche bereits in ExplorViz implementiert sind, für Android angepasst werden. So wurde unter anderem die Performance von Datenbankoperationen in ExplorViz behandelt [Zirkelbach 2015]. In Hinblick darauf kann es auch nötig sein, eine einfachere Möglichkeit zu haben um die Pointcuts variabel anzupassen. Ein wichtiger Bestandteil der zukünftigen Arbeit wird es sein, die Monitoring-Komponente an neue Android Versionen anzupassen. So wird es zum Beispiel ab Android 7.0 aufgrund 37 8. Fazit und Ausblick von fehlenden Berechtigungen nicht mehr möglich sein, sich die CPU-Auslastung über die /proc/stat Datei auslesen zu lassen. 38 Literaturverzeichnis [Arzt u. a. 2013] S. Arzt, S. Rasthofer und E. Bodden. Instrumenting android and java applications as easy as abc. In: International Conference on Runtime Verification. Springer. 2013, Seiten 364–381. (Siehe Seiten 6 und 13) [Bartel u. a. 2012] A. Bartel, J. Klein, M. Monperrus, K. Allix und Y. L. Traon. In-Vivo Bytecode Instrumentation for Improving Privacy on Android Smartphones in Uncertain Environments. arXiv preprint arXiv:1208.4536 (2012). (Siehe Seite 14) [El-Harake u. a. 2014] K. El-Harake, Y. Falcone, W. Jerad, M. Langet und M. Mamlouk. Blocking Advertisements on Android Devices using Monitoring Techniques. In: International Symposium On Leveraging Applications of Formal Methods, Verification and Validation. Springer. 2014, Seiten 239–253. (Siehe Seite 14) [Fittkau 2015] F. Fittkau. Live Trace Visualization for System and Program Comprehension in Large Software Landscapes. Dissertation. Christian-Albrechts-Universität zu Kiel, 2015, Seiten 33–34. url: http://eprints.uni-kiel.de/29511/1/diss_fittkau.pdf. (Siehe Seiten 9, 17–20) [Fittkau u. a. 2013a] F. Fittkau, J. Waller, C. Wulf, und W. Hasselbring. Live Trace Visualization for Comprehending Large Software Landscapes: The ExplorViz Approach. In: Live Trace Visualization for Comprehending Large Software Landscapes: The ExplorViz Approach. Proc. 1st IEEE International Working Conference on Software Visualization, Feb. 2013a, Seiten 80–85. (Siehe Seiten 1 und 9) [Fittkau u. a. 2016] F. Fittkau, A. Krause und W. Hasselbring. Software landscape and application visualization for system comprehension with ExplorViz. Information and Software Technology (2016). (Siehe Seite 9) [IDC 2015] IDC. International Data Corporation: Smartphone OS Market Share, 2015 Q2. 2015. url: http://www.idc.com/prodserv/smartphone-os-market-share.jsp (besucht am 04. 06. 2016). (Siehe Seite 1) [Kiczales u. a. 1997] G Kiczales, J Lamping, A Mendhekar, C Maeda, C Lopes, J Loingtier und J Irwin. Aspect-oriented programming. Band 1. Springer, 1997. (Siehe Seite 7) [Kiczales u. a. 2001] G. Kiczales, E. Hilsdale, J. Hugunin, M. Kersten, J. Palm und W. G. Griswold. An overview of AspectJ. In: European Conference on Object-Oriented Programming. Springer. 2001, Seiten 327–354. (Siehe Seite 7) [Van Hoorn u. a. 2012] A. van Hoorn, J. Waller und W. Hasselbring. Kieker: A Framework for Application Performance Monitoring and Dynamic Software Analysis. In: Proceedings of the 3rd ACM/SPEC International Conference on Performance Engineering (ICPE 2012). ACM, Apr. 2012, Seiten 247–248. (Siehe Seite 10) 39 Literaturverzeichnis [Zirkelbach 2015] C. Zirkelbach. Performance monitoring of database operations. Dissertation. Kiel University, 2015. (Siehe Seite 37) 40 Anhang 41