jvm两种方式获取对象所占用的内存
mazhen91 2018-02-27 23:38:40 浏览40 评论0摘要: 在开发过程中,我们有时需要来获取某个对象的大小,以方便我们参考,来决定开发的技术方案。jvm中提供了两种方式来获取一个对象的大小。
在开发过程中,我们有时需要来获取某个对象的大小,以方便我们参考,来决定开发的技术方案。jvm中提供了两种方式来获取一个对象的大小。
通过Instrumentation来计算对象的大小
- 编写计算代码:
package com.java.basic;
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
{
private 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) {//这个if是bug,应当去掉--teasp
// skip interned string
if (obj == ((String) obj).intern()) {
return true;
}
}
return (obj == null) || visited.containsKey(obj);
}
@SuppressWarnings("rawtypes")
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;
}
}
其中sizeof方法仅仅获取的是当前对象的大小,而该对象的如果存在对其他对象的引用,则不在计算范围以内,而fullsizeof则会计算整体的大小。
- 将该java文件进行编译,并打成jar包
- com.java.basic.SizeOfAgent .java
jar cvf sizeOfAgent.jar com/java.basic/SizeOfAgent .class
- 修改META-INF/MANIFEST.MF文件内容
Premain-Class: com.java.basic.SizeOfAgent
Boot-Class-Path:
Can-Redefine-Classes: false
注意:每个冒号后面都有一个空格,且最后一行会有一个换行
- 将该jar包导入项目
- 添加启动参数:-javaagent:E:\sizeOfAgent.jar
我这边是将该jar包放在e盘,这里填写绝对路径。
这样我们就可以通过调用该类中的sizeOf方法或者fullSizeOf方法即可。
用云栖社区APP,舒服~
【云栖快讯】直播推荐——现在预约2月28日14:00 VPN网关新品发布会直播,即可赢取SSL-VPN网关一个月免费试用,尽享安全、稳定、快捷的企业级服务!先到先得哦! 详情请点击 评论 (0) 点赞 (0) 收藏 (0)相关文章
- Java 虚拟机,Reference的认识
- JVM堆内存监测的一种方式,性能调优依旧任重道远
- JVM堆内存监测的一种方式,性能调优依旧任重道远
- JVM内存管理及GC机制
- JVM内存管理及GC机制
- Apache Spark 内存管理详解
- Apache Spark 内存管理详解
- Java 虚拟机,Reference的认识
- 认识JVM--第二篇-java对象内存模型
- Java内存模型