1b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler/* 2b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Copyright (C) 2015 The Android Open Source Project 3b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * 4b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Licensed under the Apache License, Version 2.0 (the "License"); 5b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * you may not use this file except in compliance with the License. 6b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * You may obtain a copy of the License at 7b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * 8b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * http://www.apache.org/licenses/LICENSE-2.0 9b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * 10b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Unless required by applicable law or agreed to in writing, software 11b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * distributed under the License is distributed on an "AS IS" BASIS, 12b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * See the License for the specific language governing permissions and 14b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * limitations under the License. 15b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */ 16b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 17b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerpackage com.android.ahat; 18b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 19b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport com.android.tools.perflib.heap.ClassObj; 20b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport com.android.tools.perflib.heap.Instance; 21b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerimport java.net.URI; 22b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 23b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler/** 24b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Class to render an hprof value to a DocString. 25b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */ 26b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhlerclass Value { 27b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 2877ff54b5055ec55806069c8d026b102df29857b5Richard Uhler // For string literals, we limit the number of characters we show to 2977ff54b5055ec55806069c8d026b102df29857b5Richard Uhler // kMaxChars in case the string is really long. 3077ff54b5055ec55806069c8d026b102df29857b5Richard Uhler private static int kMaxChars = 200; 3177ff54b5055ec55806069c8d026b102df29857b5Richard Uhler 32b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler /** 33b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Create a DocString representing a summary of the given instance. 34b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */ 3538f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler private static DocString renderInstance(AhatSnapshot snapshot, Instance inst) { 3638f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler DocString formatted = new DocString(); 37b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (inst == null) { 3838f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler formatted.append("(null)"); 3938f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler return formatted; 4038f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler } 4138f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler 4238f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler // Annotate roots as roots. 4338f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler if (snapshot.isRoot(inst)) { 4438f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler formatted.append("(root) "); 45b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 46b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 4738f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler 48b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Annotate classes as classes. 4938f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler DocString link = new DocString(); 50b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (inst instanceof ClassObj) { 51b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler link.append("class "); 52b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 53b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 54b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler link.append(inst.toString()); 5538f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler 56b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler URI objTarget = DocString.formattedUri("object?id=%d", inst.getId()); 5738f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler formatted.appendLink(objTarget, link); 58b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 59b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Annotate Strings with their values. 6077ff54b5055ec55806069c8d026b102df29857b5Richard Uhler String stringValue = InstanceUtils.asString(inst, kMaxChars); 61b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (stringValue != null) { 62b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler formatted.appendFormat(" \"%s", stringValue); 63b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler formatted.append(kMaxChars == stringValue.length() ? "..." : "\""); 64b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler } 65b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler 66b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler // Annotate Reference with its referent 67b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler Instance referent = InstanceUtils.getReferent(inst); 68b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler if (referent != null) { 69b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler formatted.append(" for "); 70b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler 71b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler // It should not be possible for a referent to refer back to the 72b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler // reference object, even indirectly, so there shouldn't be any issues 73b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler // with infinite recursion here. 7438f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler formatted.append(renderInstance(snapshot, referent)); 75b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 76b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 77b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Annotate DexCache with its location. 7877ff54b5055ec55806069c8d026b102df29857b5Richard Uhler String dexCacheLocation = InstanceUtils.getDexCacheLocation(inst, kMaxChars); 79b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (dexCacheLocation != null) { 80b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler formatted.appendFormat(" for %s", dexCacheLocation); 8177ff54b5055ec55806069c8d026b102df29857b5Richard Uhler if (kMaxChars == dexCacheLocation.length()) { 82b357730dd691e608f8a3d155330ab3763ce912cfRichard Uhler formatted.append("..."); 8377ff54b5055ec55806069c8d026b102df29857b5Richard Uhler } 84b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 85b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 86b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 87b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler // Annotate bitmaps with a thumbnail. 88b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler Instance bitmap = InstanceUtils.getAssociatedBitmapInstance(inst); 89b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler String thumbnail = ""; 90b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (bitmap != null) { 91c21e4e67861f38e2ebce3cce633d01fcb8de5f1fRichard Uhler URI uri = DocString.formattedUri("bitmap?id=%d", bitmap.getId()); 92b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler formatted.appendThumbnail(uri, "bitmap image"); 93b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 94b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler return formatted; 95b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 96b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler 97b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler /** 98b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler * Create a DocString summarizing the given value. 99b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler */ 10038f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler public static DocString render(AhatSnapshot snapshot, Object val) { 101b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler if (val instanceof Instance) { 10238f9eba1ad2094205410b47cd72ae3e4152c9432Richard Uhler return renderInstance(snapshot, (Instance)val); 103b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } else { 104c21e4e67861f38e2ebce3cce633d01fcb8de5f1fRichard Uhler return DocString.format("%s", val); 105b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 106b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler } 107b730b78dac047c6d8ead93ad77605bcb7414f5ceRichard Uhler} 108