<delect id="sj01t"></delect>
  1. <em id="sj01t"><label id="sj01t"></label></em>
  2. <div id="sj01t"></div>
    1. <em id="sj01t"></em>

            <div id="sj01t"></div>
            java語言

            查看java對象所占的內存大小的方法

            時間:2025-05-30 18:52:27 java語言 我要投稿
            • 相關推薦

            查看java對象所占的內存大小的方法

              做一些cache的時候,我們不可能把數據庫的所有的數據都緩存到內存里面,我們要估計緩存的大小。那么如何查看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 <Your main class>

              拿到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<Object, Object> visited = new IdentityHashMap<Object, Object>();

              Stack<Object> stack = new Stack<Object>();

              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<Object> 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;

              }

              }

              然后我們可以做一個測試:

              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<Long, List<Long>> map = ApiUtils.getHotindexBaidu();

              long size = SizeOfAgent.fullSizeOf(map);

              return new ApiActionResult("size:"+size);

              }

            【查看java對象所占的內存大小的方法】相關文章:

            java獲取Class對象的方法08-12

            java面向對象編程的方法09-19

            java面向對象編程的方法資料06-05

            關于Java中對象的銷毀方法分析09-03

            Java中創建對象的5種方法06-04

            Java的面向對象05-16

            java基礎的面向對象07-09

            Java對象和類08-27

            Java如何面向對象08-15

            <delect id="sj01t"></delect>
            1. <em id="sj01t"><label id="sj01t"></label></em>
            2. <div id="sj01t"></div>
              1. <em id="sj01t"></em>

                      <div id="sj01t"></div>
                      黄色视频在线观看