src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java

Print this page




  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.ir.debug;
  27 
  28 import java.lang.reflect.Array;
  29 import java.lang.reflect.Field;
  30 import java.lang.reflect.InvocationTargetException;
  31 import java.lang.reflect.Method;
  32 import java.lang.reflect.Modifier;
  33 import java.util.ArrayDeque;
  34 import java.util.ArrayList;
  35 import java.util.Arrays;
  36 import java.util.Deque;
  37 import java.util.IdentityHashMap;
  38 import java.util.LinkedList;
  39 import java.util.List;
  40 import java.util.Map;

  41 
  42 /**
  43  * Contains utility methods for calculating the memory usage of objects. It
  44  * only works on the HotSpot JVM, and infers the actual memory layout (32 bit
  45  * vs. 64 bit word size, compressed object pointers vs. uncompressed) from
  46  * best available indicators. It can reliably detect a 32 bit vs. 64 bit JVM.
  47  * It can only make an educated guess at whether compressed OOPs are used,
  48  * though; specifically, it knows what the JVM's default choice of OOP
  49  * compression would be based on HotSpot version and maximum heap sizes, but if
  50  * the choice is explicitly overridden with the <tt>-XX:{+|-}UseCompressedOops</tt> command line
  51  * switch, it can not detect
  52  * this fact and will report incorrect sizes, as it will presume the default JVM
  53  * behavior.
  54  */
  55 public final class ObjectSizeCalculator {
  56 
  57     /**
  58      * Describes constant memory overheads for various constructs in a JVM implementation.
  59      */
  60     public interface MemoryLayoutSpecification {


 133     // Padding for the fields of superclass before fields of subclasses are
 134     // added.
 135     private final int superclassFieldPadding;
 136 
 137     private final Map<Class<?>, ClassSizeInfo> classSizeInfos = new IdentityHashMap<>();
 138 
 139 
 140     private final Map<Object, Object> alreadyVisited = new IdentityHashMap<>();
 141     private final Map<Class<?>, ClassHistogramElement> histogram = new IdentityHashMap<>();
 142 
 143     private final Deque<Object> pending = new ArrayDeque<>(16 * 1024);
 144     private long size;
 145 
 146     /**
 147      * Creates an object size calculator that can calculate object sizes for a given
 148      * {@code memoryLayoutSpecification}.
 149      *
 150      * @param memoryLayoutSpecification a description of the JVM memory layout.
 151      */
 152     public ObjectSizeCalculator(final MemoryLayoutSpecification memoryLayoutSpecification) {
 153         memoryLayoutSpecification.getClass();
 154         arrayHeaderSize = memoryLayoutSpecification.getArrayHeaderSize();
 155         objectHeaderSize = memoryLayoutSpecification.getObjectHeaderSize();
 156         objectPadding = memoryLayoutSpecification.getObjectPadding();
 157         referenceSize = memoryLayoutSpecification.getReferenceSize();
 158         superclassFieldPadding = memoryLayoutSpecification.getSuperclassFieldPadding();
 159     }
 160 
 161     /**
 162      * Given an object, returns the total allocated size, in bytes, of the object
 163      * and all other objects reachable from it.
 164      *
 165      * @param obj the object; can be null. Passing in a {@link java.lang.Class} object doesn't do
 166      *          anything special, it measures the size of all objects
 167      *          reachable through it (which will include its class loader, and by
 168      *          extension, all other Class objects loaded by
 169      *          the same loader, and all the parent class loaders). It doesn't provide the
 170      *          size of the static fields in the JVM class that the Class object
 171      *          represents.
 172      * @return the total allocated size of the object and all other objects it
 173      *         retains.




  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.ir.debug;
  27 
  28 import java.lang.reflect.Array;
  29 import java.lang.reflect.Field;
  30 import java.lang.reflect.InvocationTargetException;
  31 import java.lang.reflect.Method;
  32 import java.lang.reflect.Modifier;
  33 import java.util.ArrayDeque;
  34 import java.util.ArrayList;
  35 import java.util.Arrays;
  36 import java.util.Deque;
  37 import java.util.IdentityHashMap;
  38 import java.util.LinkedList;
  39 import java.util.List;
  40 import java.util.Map;
  41 import java.util.Objects;
  42 
  43 /**
  44  * Contains utility methods for calculating the memory usage of objects. It
  45  * only works on the HotSpot JVM, and infers the actual memory layout (32 bit
  46  * vs. 64 bit word size, compressed object pointers vs. uncompressed) from
  47  * best available indicators. It can reliably detect a 32 bit vs. 64 bit JVM.
  48  * It can only make an educated guess at whether compressed OOPs are used,
  49  * though; specifically, it knows what the JVM's default choice of OOP
  50  * compression would be based on HotSpot version and maximum heap sizes, but if
  51  * the choice is explicitly overridden with the <tt>-XX:{+|-}UseCompressedOops</tt> command line
  52  * switch, it can not detect
  53  * this fact and will report incorrect sizes, as it will presume the default JVM
  54  * behavior.
  55  */
  56 public final class ObjectSizeCalculator {
  57 
  58     /**
  59      * Describes constant memory overheads for various constructs in a JVM implementation.
  60      */
  61     public interface MemoryLayoutSpecification {


 134     // Padding for the fields of superclass before fields of subclasses are
 135     // added.
 136     private final int superclassFieldPadding;
 137 
 138     private final Map<Class<?>, ClassSizeInfo> classSizeInfos = new IdentityHashMap<>();
 139 
 140 
 141     private final Map<Object, Object> alreadyVisited = new IdentityHashMap<>();
 142     private final Map<Class<?>, ClassHistogramElement> histogram = new IdentityHashMap<>();
 143 
 144     private final Deque<Object> pending = new ArrayDeque<>(16 * 1024);
 145     private long size;
 146 
 147     /**
 148      * Creates an object size calculator that can calculate object sizes for a given
 149      * {@code memoryLayoutSpecification}.
 150      *
 151      * @param memoryLayoutSpecification a description of the JVM memory layout.
 152      */
 153     public ObjectSizeCalculator(final MemoryLayoutSpecification memoryLayoutSpecification) {
 154         Objects.requireNonNull(memoryLayoutSpecification);
 155         arrayHeaderSize = memoryLayoutSpecification.getArrayHeaderSize();
 156         objectHeaderSize = memoryLayoutSpecification.getObjectHeaderSize();
 157         objectPadding = memoryLayoutSpecification.getObjectPadding();
 158         referenceSize = memoryLayoutSpecification.getReferenceSize();
 159         superclassFieldPadding = memoryLayoutSpecification.getSuperclassFieldPadding();
 160     }
 161 
 162     /**
 163      * Given an object, returns the total allocated size, in bytes, of the object
 164      * and all other objects reachable from it.
 165      *
 166      * @param obj the object; can be null. Passing in a {@link java.lang.Class} object doesn't do
 167      *          anything special, it measures the size of all objects
 168      *          reachable through it (which will include its class loader, and by
 169      *          extension, all other Class objects loaded by
 170      *          the same loader, and all the parent class loaders). It doesn't provide the
 171      *          size of the static fields in the JVM class that the Class object
 172      *          represents.
 173      * @return the total allocated size of the object and all other objects it
 174      *         retains.