How to view the memory size of a Java object

Source: Internet
Author: User
Tags modifier static class

Reference: Http://www.jroller.com/maxim/entry/again_about_determining_size_of

Reference: http://blog.csdn.net/xieyuooo/article/details/7068216

Why do we want to know the size of the object in memory? (1) When we do some cache, we cannot cache all the data of the database into the memory, we want to estimate the size of the cache.
(2) memory leaks, we can see the size of some objects to locate the problem, of course, there are other more efficient way, such as using mat analysis dump file
(3) Depending on the JVM's heap memory settings, we can know how many objects can be created.
Starting with Jdk5, the instrumentation API is provided, which has a method called getobjectsize (), but there are two problems with this approach:
(1) Can not be used directly. You have to implement a instrumentation Agent, and you have to put it inside the jar bag.
(2) It can only return the size of a single object and cannot return the size of the internally contained child objects.
On the first question, well resolved, declare a "Premain" method in any class to make this class an agent:
public class Sizeofagent {
static Instrumentation Inst;
/** Initializes agent * *
public static void Premain (String Agentargs, instrumentation INSTP) {
Inst = INSTP;
}
}
The JVM invokes the Premain () method at startup and passes instrumentation instance of the object, telling the JVM instrumentation the class that the agent is in, which needs to be typed into the jar bag.
Then set some properties for this file in MANIFEST.MF:
Premain-class:sizeof.agent.sizeofagent
Boot-class-path:
Can-redefine-classes:false
Java application Specifies the-javaagent parameter when it is started:
Java-javaagent:sizeofag.jar <your Main class>
After you get this instance of instrumentation, you can call the sizeof () method:
public class Sizeofagent {
static Instrumentation Inst;
// ...
public static long sizeOf (Object o) {
return Inst.getobjectsize (o);
}
}
You can then use reflection to get the size of the child object.
The complete code is as follows:
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" \ "-javaagent\" command line argument. ");
}
return Inst.getobjectsize (o);
}

/**
* Calculates full size an 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 is 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;
}
}
Then we can do a test:
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 ("xujsh", "BJ");
Long size = sizeofagent.fullsizeof (p);
SYSTEM.OUT.PRINTLN (size);
}
}
Switch to the command line:
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&GT;JAR-CVFM Size.jar MANIFEST. MF com/bj58/test/*
Marked list (manifest)
Add: com/bj58/test/sizeofagent.class (read = 3119) (write = 1698) (compressed 45%)
Add: Com/bj58/test/sizeofagent.java (read = 3147) (write = 1204) (compressed 61%)
Add: com/bj58/test/test$person.class (read = 442) (write = 305) (compressed 30%)
Add: com/bj58/test/test.class (read = 692) (write = 441) (compressed 36%)
Add: Com/bj58/test/test.java (Read = 509) (write = 290) (compressed 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

"Note" MANIFEST. MF file format requirements are more stringent, each line to meet: Key: Space value return



How to use it in a Web application.
Take my tomcat for example,
(1) Size.jar upload Tomcat's lib directory under
(2) Modify catalina.sh:
Add a line:
java_opts= "$JAVA _opts- Javaagent: $CATALINA _home/lib/size.jar " //This line is a newly added
if [-Z" $LOGGING _manager "]; then
  java_opts=" $J Ava_opts-djava.util.logging.manager=org.apache.juli.classloaderlogmanager "
Else
  java_opts=" $JAVA _ OPTS $LOGGING _manager "
Fi
(3) adds a controler to the application:
@Path (value ="/api/size ")
@GET
Public actionres Ult size () {
    map<long, list<long>> Map = Apiutils.gethotindexbaidu ();
    long size = sizeofagent.fullsizeof (map);
    return New Apiactionresult ("Size:" +size);
}
and then you can use the browser to access it.

Other also: http://www.javaspecialists.co.za/archive/Issue078.html

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.