Java对象内存计算的几种方法

发布于 2014-06-08 | 更新于 2020-09-20

使用system.gc()和java.lang.Runtime类中的freeMemory(),totalMemory(),maxMemory()这几个方法测量Java对象的大小。这种方法通常使用在需要对很多资源进行精确确定对象的大小。这种方法几乎无用等生产系统缓存的实现。这种方法的优点是数据类型大小无关的,不同的操作系统,都可以得到占用的内存。

一个更加好的方法是:http://www.javaspecialists.co.za/archive/Issue078.html。

它使用反射API用于遍历对象的成员变量的层次结构和计算所有原始变量的大小。这种方法不需要如此多的资源,可用于缓存的实现。缺点是原始类型大小是不同的不同的JVM实现对应有不同的计算方法。

JDK5.0之后Instrumentation API提供了 getObjectSize方法来计算对象占用的内存大小。

这篇文章有介绍其实现:

http://www.jroller.com/maxim/entry/again_about_determining_size_of

默认情况下并没有计算到引用对象的大小,为了计算引用对象,可以使用反射获取。下面这个方法是上面文章里面提供的一个计算包含引用对象大小的实现:

/**

  • Instrumentation agent used

  • from : http://www.jroller.com/maxim/entry/again_about_determining_size_of
    */
    public class SizeOfAgent {

    static Instrumentation inst;

    /** initializes agent */
    public static void premain(String agentArgs, Instrumentation instP) {
    inst = instP;
    }

    /**

    • Returns object size without member sub-objects.
    • @param o object to get size of
    • @return object size
      */
      public static long sizeOf(Object o) {
      if(inst == null) {
      throw new IllegalStateException(“Can not access instrumentation environment.\n” +
      “Please check if jar file containing SizeOfAgent class is \n” +
      “specified in the java’s \”-javaagent\" command line argument.");
      }
      return inst.getObjectSize(o);
      }

    /**

    • Calculates full size of object iterating over

    • its hierarchy graph.

    • @param obj object to calculate size of

    • @return object size
      */
      public static long fullSizeOf(Object obj) {
      Map<Object, Object> visited = new IdentityHashMap<Object, Object>();
      Stack stack = new Stack();

      long result = internalSizeOf(obj, stack, visited);
      while (!stack.isEmpty()) {
      result += internalSizeOf(stack.pop(), stack, visited);
      }
      visited.clear();
      return result;
      }

      private static boolean skipObject(Object obj, Map<Object, Object> visited) {
      if (obj instanceof String) {
      // skip interned string
      if (obj == ((String) obj).intern()) {
      return true;
      }
      }
      return (obj == null) // skip visited object
      || visited.containsKey(obj);
      }

      private static long internalSizeOf(Object obj, Stack stack, Map<Object, Object> visited) {
      if (skipObject(obj, visited)){
      return 0;
      }
      visited.put(obj, null);

      long result = 0;
      // get size of object + primitive variables + member pointers 
      result += SizeOfAgent.sizeOf(obj);
      
      // process all array elements
      Class clazz = obj.getClass();
      if (clazz.isArray()) {
          if(clazz.getName().length() != 2) {// skip primitive type array
              int length =  Array.getLength(obj);
              for (int i = 0; i < length; i++) {
                  stack.add(Array.get(obj, i));
              } 
          }       
          return result;
      }
      
      // process all fields of the object
      while (clazz != null) {
          Field[] fields = clazz.getDeclaredFields();
          for (int i = 0; i < fields.length; i++) {
              if (!Modifier.isStatic(fields[i].getModifiers())) {
                  if (fields[i].getType().isPrimitive()) {
                      continue; // skip primitive fields
                  } else {
                      fields[i].setAccessible(true);
                      try {
                          // objects to be estimated are put to stack
                          Object objectToAdd = fields[i].get(obj);
                          if (objectToAdd != null) {                        
                              stack.add(objectToAdd);
                          }
                      } catch (IllegalAccessException ex) { 
                          assert false; 
                      }
                      }
                  }
          }
          clazz = clazz.getSuperclass();
      }
      return result;
      

      }
      }

      本文作者: arthinking

      本文链接: https://www.itzhai.comjava-object-memory-calculate-method.html

      版权声明: 版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。

      友情链接
      破博客 IT宅
      关联账号
      公众号:IT宅
      公众号:IT宅

      IT宅技术博客公众号,博客更新动态同步至公众号。扫码关注公众号及时获取更新:↓↓↓

      公众号:Java架构杂谈
      公众号:Java架构杂谈

      IT宅的Java专业技术公众号,只输出精品文章,更新评率较低。

      联系我
      1225538383@qq.com
      arthinking
      arthinking

      微信联系我

      更多信息
      暂无

      粤ICP备18081492号 © 2011 – 2024 IT宅. Designed by 帅旋. arthinking@itzhai. All Rights Reserved.
      ×
      IT宅

      关注公众号及时获取网站内容更新。