新建一个maven工程

我们先在IDEA中新建一个名为ObjectSizeFetcherAgent的maven工程,如下图:

在maven项目中的pom.xml中新增一个打jar包的插件,如下:

  <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<testExcludes>
<testExclude>/src/test/**</testExclude>
</testExcludes>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<!--使用manifestFile属性配置自定义的参数文件所在的-->
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>

  在项目的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<Object> visited = new HashSet<Object>();
Deque<Object> 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<Object> 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对象所占内存大小的更多相关文章

  1. 4种方法教你如何查看java对象所占内存大小

    摘要:本文讲述4种查看java对象所占内存大小的方法 本文分享自华为云社区<查看java对象所占内存大小>,作者:xiewenci. 计算java对象所占内存大小 1.使用jdk8自带AP ...

  2. 复杂Java对象所占内存的大小

    我们在Java单个对象内存布局中讲解了单个简单的Java对象所占内存的大小的计算.那么这篇文章主要是讲解复杂Java对象所占内存大小的计算,我们把继承.复合的对象称为复杂对象 继承对象 class P ...

  3. 如何计算Java对象所占内存的大小

    [ 简单总结: 随便一个java项目,引入jar包: lucene-core-4.0.0.jar 如果是 maven项目,直接用如下依赖: <dependency> <groupId ...

  4. 一个Java对象到底占多大内存

    最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...

  5. 一个Java对象到底占多大内存?(转)

    最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...

  6. 【转】一个Java对象到底占多大内存?

    最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...

  7. 获取JAVA对象占用的内存大小

    介绍两种获取JAVA对象内存大小的方法. 第一种:Instrumentation 简介: 使用java.lang.instrument 的Instrumentation来获取一个对象的内存大小.利用I ...

  8. JAVA数组所占内存大小的对比

    1.两个数据模型 第一个是基本类型数组,第二个使用的是Float对象数组 public class SummaryModel{ private float[] summaryData; public ...

  9. 高端面试必备:一个Java对象占用多大内存

    这个问题一般会出现在稍微高端一点的 Java 面试环节.要求面试者不仅对 Java 基础知识熟悉,更重要的是要了解内存模型. Java 对象模型 HotSpot JVM 使用名为 oops (Ordi ...

随机推荐

  1. 【剑指offer】面试题 21. 调整数组顺序使奇数位于偶数前面

    面试题 21. 调整数组顺序使奇数位于偶数前面

  2. STS,修改Ctrl+Shift+R匹配类的配置

    在使用STS(Spring Tools)时,每次通过Ctrl+Shift+R查询类时,会出来一堆不想看到的类.如下所示: 上面的.class文件和父项目中的.java文件,在匹配类时,是不想看到的. ...

  3. 遇到了NameError: name ‘name’ is not defined 这样的错误。

    改正:__name__ == "__main__" name的左右两边各有两条下划线,不是左右两边各有一条

  4. django settings.py 配置文件

    目录 settings.py 配置文件 settings.py 配置文件 import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.ab ...

  5. 38 多线程(十)——volatile 数据同步

    在多线程并发的情况下,同一个变量被多个线程调用,那修改的数据就不会每分每秒保持一致.例如,对于某个变量a,线程1对它进行一套操作,线程2又对它进行另一套操作,但如果cpu太忙了,太忙了,假设cpu都用 ...

  6. AttributeError: 'sys.flags' object has no attribute 'utf8_mode'

    AttributeError: 'sys.flags' object has no attribute 'utf8_mode' pycharm工程的py版本是3.6,结果即使使用py3.7编译后的py ...

  7. docker(四):集群swarm

    docker使用入门(四):集群swarm swarm是一组位于同一集群且运行docker的机器,用户可以通过swarm manager向swarm输入命令,swarm中的机器可以是虚拟机也可以是物理 ...

  8. 百度云服务接口错误:Parameter invalid, the key input with filter parameter is not searchfilter column key

    百度LBS云服务接口: 地址:http://lbsyun.baidu.com/index.php?title=lbscloud/api/geosearch 访问接口:http://api.map.ba ...

  9. 原子类 Atomic

    @Testpublic void testAtomicBoolean() { AtomicBoolean atomicBoolean = new AtomicBoolean(); boolean b ...

  10. Spring Cloud Alibaba学习笔记(24) - Spring Boot Actuator 监控数据可视化:Spring Boot Admin

    我们都知道,Spring Boot Actuator 提供监控数据是Json数据,在某种程度来说并不利于分析查看,那么如何将其进行可视化呢?我们有很多种选择,但是目前在这个领域,最流行的是Spring ...