1 /* 2 * Copyright (C) 2016 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.heapdump; 18 19 import com.android.ahat.dominators.DominatorsComputation; 20 import java.util.List; 21 22 /** 23 * A parsed heap dump. 24 * It contains methods to access the heaps, allocation sites, roots, classes, 25 * and instances from the parsed heap dump. 26 */ 27 public class AhatSnapshot implements Diffable<AhatSnapshot> { 28 private final Site mRootSite; 29 30 private final SuperRoot mSuperRoot; 31 32 // List of all ahat instances. 33 private final Instances<AhatInstance> mInstances; 34 35 private List<AhatHeap> mHeaps; 36 37 private AhatSnapshot mBaseline = this; 38 AhatSnapshot(SuperRoot root, Instances<AhatInstance> instances, List<AhatHeap> heaps, Site rootSite)39 AhatSnapshot(SuperRoot root, 40 Instances<AhatInstance> instances, 41 List<AhatHeap> heaps, 42 Site rootSite) { 43 mSuperRoot = root; 44 mInstances = instances; 45 mHeaps = heaps; 46 mRootSite = rootSite; 47 48 // Update registered native allocation size. 49 for (AhatInstance cleaner : mInstances) { 50 AhatInstance.RegisteredNativeAllocation nra = cleaner.asRegisteredNativeAllocation(); 51 if (nra != null) { 52 nra.referent.addRegisteredNativeSize(nra.size); 53 } 54 } 55 56 AhatInstance.computeReverseReferences(mSuperRoot); 57 DominatorsComputation.computeDominators(mSuperRoot); 58 AhatInstance.computeRetainedSize(mSuperRoot, mHeaps.size()); 59 60 for (AhatHeap heap : mHeaps) { 61 heap.addToSize(mSuperRoot.getRetainedSize(heap)); 62 } 63 64 mRootSite.prepareForUse(0, mHeaps.size()); 65 } 66 67 /** 68 * Returns the instance with the given id in this snapshot. 69 * Where the id of an instance x is x.getId(). 70 * Returns null if no instance with the given id is found. 71 * 72 * @param id the id of the instance to find 73 * @return the instance with the given id 74 */ findInstance(long id)75 public AhatInstance findInstance(long id) { 76 return mInstances.get(id); 77 } 78 79 /** 80 * Returns the AhatClassObj with the given id in this snapshot. 81 * Where the id of a class object x is x.getId(). 82 * Returns null if no class object with the given id is found. 83 * 84 * @param id the id of the class object to find 85 * @return the class object with the given id 86 */ findClassObj(long id)87 public AhatClassObj findClassObj(long id) { 88 AhatInstance inst = findInstance(id); 89 return inst == null ? null : inst.asClassObj(); 90 } 91 92 /** 93 * Returns the heap with the given name. 94 * Where the name of a heap x is x.getName(). 95 * Returns null if no heap with the given name could be found. 96 * 97 * @param name the name of the heap to get 98 * @return the heap with the given name 99 */ getHeap(String name)100 public AhatHeap getHeap(String name) { 101 // We expect a small number of heaps (maybe 3 or 4 total), so a linear 102 // search should be acceptable here performance wise. 103 for (AhatHeap heap : getHeaps()) { 104 if (heap.getName().equals(name)) { 105 return heap; 106 } 107 } 108 return null; 109 } 110 111 /** 112 * Returns a list of heaps in the snapshot in canonical order. 113 * <p> 114 * Note: modifications to the returned list are visible to this 115 * AhatSnapshot, which is used by diff to insert place holder heaps. 116 * 117 * @return list of heaps 118 */ getHeaps()119 public List<AhatHeap> getHeaps() { 120 return mHeaps; 121 } 122 123 /** 124 * Returns a collection of "rooted" instances. 125 * An instance is "rooted" if it is a GC root, or if it is retained by more 126 * than one GC root. These are reachable instances that are not immediately 127 * dominated by any other instance in the heap. 128 * 129 * @return collection of rooted instances 130 */ getRooted()131 public List<AhatInstance> getRooted() { 132 return mSuperRoot.getDominated(); 133 } 134 135 /** 136 * Returns the root allocation site for this snapshot. 137 * 138 * @return the root allocation site 139 */ getRootSite()140 public Site getRootSite() { 141 return mRootSite; 142 } 143 144 /** 145 * Returns the site associated with the given id. 146 * Where the id of a site x is x.getId(). 147 * Returns the root site if no site with the given id is found. 148 * 149 * @param id the id of the site to get 150 * @return the site with the given id 151 */ getSite(long id)152 public Site getSite(long id) { 153 Site site = mRootSite.findSite(id); 154 return site == null ? mRootSite : site; 155 } 156 setBaseline(AhatSnapshot baseline)157 void setBaseline(AhatSnapshot baseline) { 158 mBaseline = baseline; 159 } 160 161 /** 162 * Returns true if this snapshot has been diffed against a different 163 * snapshot. 164 * 165 * @return true if the snapshot has been diffed 166 */ isDiffed()167 public boolean isDiffed() { 168 return mBaseline != this; 169 } 170 getBaseline()171 @Override public AhatSnapshot getBaseline() { 172 return mBaseline; 173 } 174 isPlaceHolder()175 @Override public boolean isPlaceHolder() { 176 return false; 177 } 178 } 179