新建一个maven工程
我们先在IDEA中新建一个名为ObjectSizeFetcherAgent的maven工程,如下图:
在maven项目中的pom.xml中新增一个打jar包的插件,如下:
org.apache.maven.plugins
maven-compiler-plugin
3.1
1.8
1.8
/src/test/**
utf-8
org.apache.maven.plugins
maven-jar-plugin
3.0.2
${project.build.outputDirectory}/META-INF/MANIFEST.MF
在项目的resources中新建一个名为META-INF的目录,在这个目录下新建一个名为MANIFEST.MF的属性文件,如下图:
项目的JDK设置为1.8,如下图:
编写获取Java对象内存的工具方法
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.Set;
public class ObjectSizeFetcher {
// instrumentation 是一个 java.lang.instrument.Instrumentation 的实例,由 JVM 自动传入
private static Instrumentation instrumentation;
/**
* 这个方法先于主方法(main)执行
* @param args
* @param inst
*/
public static void premain(String args, Instrumentation inst) {
instrumentation = inst;
}
/**
* 直接计算当前对象占用空间大小,包括当前类及超类的基本类型实例字段大小、
* 引用类型实例字段引用大小、实例基本类型数组总占用空间、实例引用类型数组引用本身占用空间大小;
* 但是不包括超类继承下来的和当前类声明的实例引用字段的对象本身的大小、实例引用数组引用的对象本身的大小
*
* @param o 需要计算内存的对象
* @return 返回内存大小
*/
public static long sizeOf(Object o) {
return instrumentation.getObjectSize(o);
}
/**
* 递归计算当前对象占用空间总大小,包括当前类和超类的实例字段大小以及实例字段引用对象大小
* 注意:这个方法如果你看不懂也没关系,会用就行
*
* @param objP
* @return
* @throws IllegalAccessException
*/
public static long fullSizeOf(Object objP) throws IllegalAccessException {
Set visited = new HashSet();
Deque toBeQueue = new ArrayDeque<>();
toBeQueue.add(objP);
long size = 0L;
while (toBeQueue.size() > 0) {
Object obj = toBeQueue.poll();
//sizeOf的时候已经计基本类型和引用的长度,包括数组
size += skipObject(visited, obj) ? 0L : sizeOf(obj);
Class> tmpObjClass = obj.getClass();
if (tmpObjClass.isArray()) {
//[I , [F 基本类型名字长度是2
if (tmpObjClass.getName().length() > 2) {
for (int i = 0, len = Array.getLength(obj); i < len; i++) {
Object tmp = Array.get(obj, i);
if (tmp != null) {
//非基本类型需要深度遍历其对象
toBeQueue.add(Array.get(obj, i));
}
}
}
} else {
while (tmpObjClass != null) {
Field[] fields = tmpObjClass.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) //静态不计
|| field.getType().isPrimitive()) { //基本类型不重复计
continue;
}
field.setAccessible(true);
Object fieldValue = field.get(obj);
if (fieldValue == null) {
continue;
}
toBeQueue.add(fieldValue);
}
tmpObjClass = tmpObjClass.getSuperclass();
}
}
}
return size;
}
/**
* String.intern的对象不计;计算过的不计,也避免死循环
*
* @param visited
* @param obj
* @return
*/
static boolean skipObject(Set visited, Object obj) {
if (obj instanceof String && obj == ((String) obj).intern()) {
return true;
}
return visited.contains(obj);
}
}
计算一个对象的大小
我们在项目工程中新建一个名为Point的类,然后写一个main方法来测试new Point()占用内存空间的大小,代码如下:
public class Point {
private int x;
private int y;
public static void main(String [] args) {
System.out.println(ObjectSizeFetcher.sizeOf(new Point()));
}
}
我们在文件resources/META-INF/MANIFEST.MF中新增如下一行属性配置:
Premain-Class: com.twq.ObjectSizeFetcher
maven打包,如下:
打开操作系统的cmd,进入到上面的jar包所在的目录,如下图:
执行如下的命令:
java -javaagent:ObjectSizeFetcherAgent-1.0-SNAPSHOT.jar Point
得到的结果如下:
复杂Java对象所占内存的大小
我们在Java单个对象内存布局中讲解了单个简单的Java对象所占内存的大小的计算.那么这篇文章主要是讲解复杂Java对象所占内存大小的计算,我们把继承.复合的对象称为复杂对象 继承对象 class P ...
如何计算Java对象所占内存的大小
[ 简单总结: 随便一个java项目,引入jar包: lucene-core-4.0.0.jar 如果是 maven项目,直接用如下依赖:
一个Java对象到底占多大内存
最近在读,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...
一个Java对象到底占多大内存?(转)
最近在读,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...
【转】一个Java对象到底占多大内存?
最近在读,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...
获取JAVA对象占用的内存大小
介绍两种获取JAVA对象内存大小的方法. 第一种:Instrumentation 简介: 使用java.lang.instrument 的Instrumentation来获取一个对象的内存大小.利用I ...
JAVA数组所占内存大小的对比
1.两个数据模型 第一个是基本类型数组,第二个使用的是Float对象数组 public class SummaryModel{ private float[] summaryData; public ...
一个 Java 对象到底有多大?
阅读本文大概需要 2.8 分钟. 出处:http://u6.gg/swLPg 编写 Java 代码的时候,大多数情况下,我们很少关注一个 Java 对象究竟有多大(占据多少内存),更多的是关注业务与逻 ...
java中基本类型封装对象所占内存的大小(转)
这是一个程序,java中没有现成的sizeof的实现,原因主要是java中的基本数据类型的大小都是固定的,所以看上去没有必要用sizeof这个关键字. 实现的想法是这样的:java.lang.Runt ...
随机推荐
嵌入式实时操作系统μCOS原理与实践任务控制与时间的解析
/*************************************************************************************************** ...
Uestc_suibian 暑假集训总结
唉,终于组队了,终于可以只BB了,我就BB,我就不上! 和Xiper以及chenxh组队了- 下面是总结: day1 第一天吃饱喝足,然后就上路了,我一开始就看到了C题大水题,但是我不敢想象这道题居然 ...
(三大框架SSH)面试题锦集
http://wwwblogs/dieyf/p/4109233.html
Blue Jeans(串)
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10083 Accepted: 4262 Description The ...
(转载)PHP怎么获取MySQL执行sql语句的查询时间
(转载自CSDN) 方法一: //计时开始 runtime(); //执行查询 mysql_query($sql); //计时结束. echo runtime(1); //计时函数 function ...
ASIHttpRequest:创建队列、下载请求、断点续传、解压缩
ps:本文转载自网络:http://ryan.easymorse/?p=12 感谢作者 工程完整代码下载地址:RequestTestDownload1 可完成: 下载指定链接的zip压缩文件 ...
C++ 哈希表 (hashtable) 用于保存简单的数据,及数据查找,数据删除
/*hashtable.h*/ #include #include #include using namesp ...
Java之路——Java初接触
本文大纲 1.Java是什么 2.Java历史 3.Java技术范围 3.1 Java SE平台技术范围 3.2 Java EE技术范围 3.3 Java 体系技术范围 4.总结 1.Java是什么 ...
java 源码编译
Java语言的“编译期”其实是一段“不确定”的操作过程,因为它可能是指一个前端编译器(叫“编译器的前段”更准确)——把*.java文件转变成*.class文件的过程:也可能是虚拟机的后端运行期编译器( ...
rhel 配置centos源
1.删除自带的yum包,清除/etc/yum.repos.d下面的文件 rpm -qa|grep yum|xargs rpm -e --nodeps(不检查依赖,直接删除rpm包) 2.安装cento ...
更多推荐
java 打印对象大小_如何获取一个Java对象所占内存大小
发布评论