<address id="ousso"></address>
<form id="ousso"><track id="ousso"><big id="ousso"></big></track></form>
  1. 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

    <address id="ousso"></address>
    <form id="ousso"><track id="ousso"><big id="ousso"></big></track></form>
    1. 日日做夜狠狠爱欧美黑人