Home | History | Annotate | Download | only in heapdump
      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 
     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    */
     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    */
     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    */
    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    */
    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    */
    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    */
    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    */
    152   public Site getSite(long id) {
    153     Site site = mRootSite.findSite(id);
    154     return site == null ? mRootSite : site;
    155   }
    156 
    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    */
    167   public boolean isDiffed() {
    168     return mBaseline != this;
    169   }
    170 
    171   @Override public AhatSnapshot getBaseline() {
    172     return mBaseline;
    173   }
    174 
    175   @Override public boolean isPlaceHolder() {
    176     return false;
    177   }
    178 }
    179