为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

如何查看java对象所占的内存大小

2017-12-19 9页 doc 27KB 30阅读

用户头像

is_180829

暂无简介

举报
如何查看java对象所占的内存大小如何查看java对象所占的内存大小 如何查看java对象所占的内存大小 我们为什么想要知道对象所占对内存的大小呢, (1)做一些cache的时候,我们不可能把数据库的所有的数据都缓存到内存里面,我们要估计缓存的大小。 (2)内存泄露的时候,我们可以查看某些对象的大小来定位问题,当然还有其他的更有效的方式,比如使用MAT分析dump文件 (3)根据jvm的堆内存设置,我们可以知道最多可以创建多少个对象。 从jdk5开始,提供了Instrumentation API,它有一个叫做getObjectSize()的方法,但是...
如何查看java对象所占的内存大小
如何查看java对象所占的内存大小 如何查看java对象所占的内存大小 我们为什么想要知道对象所占对内存的大小呢, (1)做一些cache的时候,我们不可能把数据库的所有的数据都缓存到内存里面,我们要估计缓存的大小。 (2)内存泄露的时候,我们可以查看某些对象的大小来定位问题,当然还有其他的更有效的方式,比如使用MAT分析dump文件 (3)根据jvm的堆内存设置,我们可以知道最多可以创建多少个对象。 从jdk5开始,提供了Instrumentation API,它有一个叫做getObjectSize()的方法,但是,这个方法存在两个问题: (1)不可以直接使用。必须要实现一个Instrumentation Agent,还得放到jar包里面。 (2)它只能返回单个对象的大小,不能返回内部包含的子对象的大小。 关于第一个问题,很好解决,在任何一个类里面声明一个"premain"方法,就可以把这个类做成是一个agent: public class SizeOfAgent { static Instrumentation inst; /** initializes agent */ public static void premain(String agentArgs, Instrumentation instP) { inst = instP; } } jvm在启动的时候会调用premain()方法,同时会传递Instrumentation这个对象实例,要告诉jvm Instrumentation agent所在的类,需要把这个类打到jar包里面, 然后在manifest.mf这个文件设置一些属性: Premain-Class: sizeof.agent.SizeOfAgent Boot-Class-Path: Can-Redefine-Classes: false java应用在启动的时候,指定-javaagent参数: java -javaagent:sizeofag.jar 拿到Instrumentation这个实例以后,就可以调用sizeOf()方法了: public class SizeOfAgent { static Instrumentation inst; // ... public static long sizeOf(Object o) { return inst.getObjectSize(o); } } 然后可以使用反射来获取子对象的大小。文章由郑州北大青鸟 整理 完整的代码如下: package com.bj58.test; import java.lang.instrument.Instrumentation; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.IdentityHashMap; import java.util.Map; import java.util.Stack; 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 visited = new IdentityHashMap(); 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 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 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; } } 然后我们可以做一个测试: public class Test { static class Person{ private int id; private String name; private String address; public Person(int id, String name, String address) { this.id = id; this.name = name; this.address = address; } } public static void main(String[] args) throws Exception { Person p = new Person(12, "xujsh","bj"); long size = SizeOfAgent.fullSizeOf(p); System.out.println(size); } } 切换到命令行: D:\workspace\objsize\src>java -version java version "1.6.0_22" Java(TM) SE Runtime Environment (build 1.6.0_22-b04) Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing) D:\workspace\objsize\src>javac com/bj58/test/*.java D:\workspace\objsize\src>jar -cvfm size.jar MANIFEST.MF com/bj58/test/* 标明清单(manifest) 增加:com/bj58/test/SizeOfAgent.class(读入= 3119) (写出= 1698)(压缩了 45%) 增加:com/bj58/test/SizeOfAgent.java(读入= 3147) (写出= 1204)(压缩了 61%) 增加:com/bj58/test/Test$Person.class(读入= 442) (写出= 305)(压缩了 30%) 增加:com/bj58/test/Test.class(读入= 692) (写出= 441)(压缩了 36%) 增加:com/bj58/test/Test.java(读入= 509) (写出= 290)(压缩了 43%) D:\workspace\objsize\src>java -javaagent:size.jar com.bj58.test.Test 24 MANIFEST.MF: Manifest-Version: 1.0 Main-Class: com.bj58.test.Test Premain-Class: com.bj58.test.SizeOfAgent Boot-Class-Path: Can-Redefine-Classes: false 【注意】MANIFEST.MF文件的格式要求比较严格,每一行要满足:key:空格value回车 如何在web应用程序里面使用呢, 以我的tomcat为例, (1)把size.jar上传tomcat的lib目录下面 (2)修改catalina.sh: 添加一行: JAVA_OPTS="$JAVA_OPTS -javaagent:$CATALINA_HOME/lib/size.jar" //这一行是新添加的 if [ -z "$LOGGING_MANAGER" ]; then JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" else JAVA_OPTS="$JAVA_OPTS $LOGGING_MANAGER" fi (3)在应用里面添加一个controler: @Path(value = "/api/size") @GET public ActionResult size() { Map> map = ApiUtils.getHotindexBaidu(); long size = SizeOfAgent.fullSizeOf(map); return new ApiActionResult("size:"+size); } 然后就可以用浏览器来访问了。
/
本文档为【如何查看java对象所占的内存大小】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
热门搜索

历史搜索

    清空历史搜索