0%
这是一片思考的空间 -- arthinking
Spring 重构&代码整洁之道 软件设计 JVM 并发编程 数据结构与算法 分布式 存储 网络 微服务 设计模式
Java技术栈 - 涉及Java技术体系

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

使用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;
    

    }
    }

欢迎关注我的其它发布渠道

订阅IT宅
内功修炼
Java技术栈
Java架构杂谈是IT宅精品文章公众号,欢迎订阅:
📄 网络基础知识:两万字长文50+张趣图带你领悟网络编程的内功心法 📄 HTTP发展史:三万长文50+趣图带你领悟web编程的内功心法 📄 HTTP/1.1:可扩展,可靠性,请求应答,无状态,明文传输 📄 HTTP/1.1报文详解:Method,URI,URL,消息头,消息体,状态行 📄 HTTP常用请求头大揭秘 📄 HTTPS:网络安全攻坚战 📄 HTTP/2:网络安全传输的快车道 📄 HTTP/3:让传输效率再一次起飞 📄 高性能网络编程:图解Socket核心内幕以及五大IO模型 📄 高性能网络编程:三分钟短文快速了解信号驱动式IO 📄 高性能网络编程:彻底弄懂IO复用 - IO处理杀手锏,带您深入了解select,poll,epoll 📄 高性能网络编程:异步IO:新时代的IO处理利器 📄 高性能网络编程:网络编程范式 - 高性能服务器就这么回事 📄 高性能网络编程:性能追击 - 万字长文30+图揭秘8大主流服务器程序线程模型
📄 Java内存模型:如果有人给你撕逼Java内存模型,就把这些问题甩给他 📄 一文带你彻底理解同步和锁的本质(干货) 📄 AQS与并发包中锁的通用实现 📄 ReentrantLock介绍与使用 📄 ReentrantReadWriteLock介绍与使用 📄 ReentrantLock的Condition原理解析 📄 如何优雅的中断线程 📄 如何优雅的挂起线程 📄 图解几个好玩的并发辅助工具类 📄 图解BlockingQueue阻塞队列
📄 消息队列那么多,为什么建议深入了解下RabbitMQ? 📄 高并发异步解耦利器:RocketMQ究竟强在哪里? 📄 Kafka必知必会18问:30+图带您看透Kafka
📄 洞悉MySQL底层架构:游走在缓冲与磁盘之间 📄 SQL运行内幕:从执行原理看调优的本质 📄 洞悉Redis技术内幕:缓存,数据结构,并发,集群与算法