1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ahat; 18 19 import com.android.ahat.heapdump.AhatSnapshot; 20 import com.android.ahat.heapdump.Diff; 21 import com.android.tools.perflib.heap.ProguardMap; 22 import com.sun.net.httpserver.HttpServer; 23 import java.io.File; 24 import java.io.IOException; 25 import java.io.PrintStream; 26 import java.net.InetAddress; 27 import java.net.InetSocketAddress; 28 import java.text.ParseException; 29 import java.util.concurrent.Executors; 30 31 public class Main { 32 help(PrintStream out)33 public static void help(PrintStream out) { 34 out.println("java -jar ahat.jar [OPTIONS] FILE"); 35 out.println(" Launch an http server for viewing the given Android heap dump FILE."); 36 out.println(""); 37 out.println("OPTIONS:"); 38 out.println(" -p <port>"); 39 out.println(" Serve pages on the given port. Defaults to 7100."); 40 out.println(" --proguard-map FILE"); 41 out.println(" Use the proguard map FILE to deobfuscate the heap dump."); 42 out.println(" --baseline FILE"); 43 out.println(" Diff the heap dump against the given baseline heap dump FILE."); 44 out.println(" --baseline-proguard-map FILE"); 45 out.println(" Use the proguard map FILE to deobfuscate the baseline heap dump."); 46 out.println(""); 47 } 48 main(String[] args)49 public static void main(String[] args) throws IOException { 50 int port = 7100; 51 for (String arg : args) { 52 if (arg.equals("--help")) { 53 help(System.out); 54 return; 55 } 56 } 57 58 File hprof = null; 59 File hprofbase = null; 60 ProguardMap map = new ProguardMap(); 61 ProguardMap mapbase = new ProguardMap(); 62 for (int i = 0; i < args.length; i++) { 63 if ("-p".equals(args[i]) && i + 1 < args.length) { 64 i++; 65 port = Integer.parseInt(args[i]); 66 } else if ("--proguard-map".equals(args[i]) && i + 1 < args.length) { 67 i++; 68 try { 69 map.readFromFile(new File(args[i])); 70 } catch (IOException|ParseException ex) { 71 System.out.println("Unable to read proguard map: " + ex); 72 System.out.println("The proguard map will not be used."); 73 } 74 } else if ("--baseline-proguard-map".equals(args[i]) && i + 1 < args.length) { 75 i++; 76 try { 77 mapbase.readFromFile(new File(args[i])); 78 } catch (IOException|ParseException ex) { 79 System.out.println("Unable to read baselline proguard map: " + ex); 80 System.out.println("The proguard map will not be used."); 81 } 82 } else if ("--baseline".equals(args[i]) && i + 1 < args.length) { 83 i++; 84 if (hprofbase != null) { 85 System.err.println("multiple baseline heap dumps."); 86 help(System.err); 87 return; 88 } 89 hprofbase = new File(args[i]); 90 } else { 91 if (hprof != null) { 92 System.err.println("multiple input files."); 93 help(System.err); 94 return; 95 } 96 hprof = new File(args[i]); 97 } 98 } 99 100 if (hprof == null) { 101 System.err.println("no input file."); 102 help(System.err); 103 return; 104 } 105 106 // Launch the server before parsing the hprof file so we get 107 // BindExceptions quickly. 108 InetAddress loopback = InetAddress.getLoopbackAddress(); 109 InetSocketAddress addr = new InetSocketAddress(loopback, port); 110 HttpServer server = HttpServer.create(addr, 0); 111 112 System.out.println("Processing hprof file..."); 113 AhatSnapshot ahat = AhatSnapshot.fromHprof(hprof, map); 114 115 if (hprofbase != null) { 116 System.out.println("Processing baseline hprof file..."); 117 AhatSnapshot base = AhatSnapshot.fromHprof(hprofbase, mapbase); 118 119 System.out.println("Diffing hprof files..."); 120 Diff.snapshots(ahat, base); 121 } 122 123 server.createContext("/", new AhatHttpHandler(new OverviewHandler(ahat, hprof, hprofbase))); 124 server.createContext("/rooted", new AhatHttpHandler(new RootedHandler(ahat))); 125 server.createContext("/object", new AhatHttpHandler(new ObjectHandler(ahat))); 126 server.createContext("/objects", new AhatHttpHandler(new ObjectsHandler(ahat))); 127 server.createContext("/site", new AhatHttpHandler(new SiteHandler(ahat))); 128 server.createContext("/bitmap", new BitmapHandler(ahat)); 129 server.createContext("/style.css", new StaticHandler("style.css", "text/css")); 130 server.setExecutor(Executors.newFixedThreadPool(1)); 131 System.out.println("Server started on localhost:" + port); 132 133 server.start(); 134 } 135 } 136 137