对象大小的计算

正如笔者看的这篇文章所描述的一样,当我们试图获取一个JVM中的对象实际占用的空间大小时。通常使用的方法是徒手计算,或者通过gc计算前后内存差来估计对象大小。而今天要介绍的方法——利用Instrumentation来准确获取对象大小的方法——拒绝手算,拒绝估算!

搭建HelloWorld

关键在于获取Instrumentation的实例,通过查看此接口的JavaDoc可以知道有两种方法:

*When a JVM is launched in a way that indicates an agent class. In that case an Instrumentation instance is passed to the premain method of the agent class. * 也就是说在JVM启动的时候会有一个agent类的premain方法会接收到一个Instrumentation实例。这种方法需要我们自己实现一个agent的实现类,并复写premain方法来保存此实例即可。

When a JVM provides a mechanism to start agents sometime after the JVM is launched. In that case an Instrumentation instance is passed to the agentmain method of the agent code. 这种方法其实也是通过agent来获取实例,只不过这里的agent是在JVM启动后才运行起来的。

我们这里通过第一种方法来做一个Demo,简单概括以下流程:

1. 编写agent实现类,在类中覆写premain(),并打成jar包(在这里就是AgentClass-jar-with-dependencies.jar)。注意在打包的时候需要修改META-INF/MANIFEST.MF文件增加一行

Premain-Class: MyAgent

在这里我们是通过maven的maven-assembly-plugin插件来实现的修改的。更多关于META-INF/MANIFEST.MF可以看这篇文章。

编写调用Instrumentation实例的测试类

通过-javaagent:jar/AgentClass-jar-with-dependencies.jar参数启动测试类

注意:因为在jdk6之后默认开启了指针压缩,为了方便理解,最好在启动的时候加入-XX:-UseCompressedOops关闭之。

详细的代码结构:

.

├── jar

│   └── AgentClass-jar-with-dependencies.jar

├── pom.xml

└── src

└── main

└── java

├── MyAgent.java

└── TestSize.java

/*MyAgent.java*/

import java.lang.instrument.Instrumentation;

public class MyAgent {

private static Instrumentation inst;

/**

* 这个方法必须写,在agent调用时会被启用

*/

public static void premain(String agentArgs, Instrumentation instP) {

System.out.println("On premain, agentArgs: [" + agentArgs + "]");

inst = instP;

}

/**

* 用来测量java对象的大小,调用了Instrumentation实例方法

*/

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);

}

}

/*pom.xml*/

AgentClass

org.apache.maven.plugins

maven-assembly-plugin

2.5.5

MyAgent

jar-with-dependencies

make-assembly

package

single

/*TestSize.java*/

public class TestSize {

public void test(){

System.out.println("int:\t" + MyAgent.sizeOf(1));//输出为16

}

public static void main(String []args) {

new TestSize().test();

}

}

到这里我们就完成了一个简单的HelloWorld,如果想要深入了解Instrumentation的细节,参考另一篇文章。下面我们继续来看我们得到的实验结果。

对象空间结构

普通对象结构

在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。如下图所示:

对象头:包含两个部分,第一部分markword,用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32bit和64bit,官方称它为“MarkWord”。第二部分是klass,类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例,同样在32位和64位的虚拟机(未开启压缩指针)中分别为32bit和64bit。

对象实际数据:为实际在堆中分配了内存的类属性。

对齐填充:HotSpot VM的自动内存管理系统要求所有的对象起始位置必须是8的整数倍,所以对于不足n*8byte的对象进行填充对齐。

有了以上的信息,我们就可以进行更多的假设校验了,(以下数据来自64位jvm,关闭指针压缩)

类定义

大小(bytes)

说明

public class SimpleVainClass{}

16

仅包含对象头

(int)1

24

猜测本来一个基础类型int仅包含4字节,但是因为转成了对象,加了一个对象头的大小16字节,补齐为24

Integer(1)

24

同上

public class SimpleClassWithInt{ private int i = 3;}

32

按理应该是对象头16字节 + int对象指针8字节 = 24字节,为什么这里出现32字节??望高人指教

instrumentation java_使用Instrumentation计算java对象大小相关推荐

  1. 计算 java_两种计算Java对象大小的方法(转)

    原文:http://blog.csdn.net/iter_zc/article/details/41822719 另一篇类似文章:http://www.cnblogs.com/magialmoon/p ...

  2. 聊聊JVM(三)两种计算Java对象大小的方法

    普通对象的结构如下,按64位机器的长度计算 1. 对象头(_mark), 8个字节 2. Oop指针,如果是32G内存以下的,默认开启对象指针压缩,4个字节 3. 数据区 4.Padding(内存对齐 ...

  3. 两种计算Java对象大小的方法

    之前想研究一下unsafe类,碰巧在网上看到了这篇文章,觉得写得很好,就转载过来.原文出处是: http://blog.csdn.net/iter_zc/article/details/4182271 ...

  4. java char占用多少字节_Java虚拟机:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

  5. Java对象大小内幕浅析

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  6. 如何计算java对象大小

    背景 目前我们系统的业务代码中大量使用了LocalCache的方式做本地缓存,而且cache的maxSize通常设的比较大,比如10000.我们的业务系统中就使用了size为10000的15个本地缓存 ...

  7. 怎么计算java对象的大小?

    java编程中处处离不开对象,是否了解对象在内存中结构?是否知道如何计算对象在内存中具体大小呢?本篇文章将想你介绍对象在内存中布局以及如何计算对象大小. 内存结构 在HotSpot虚拟机中,对象在内存 ...

  8. 使用JOL工具计算Java对象的大小

    注意:本文默认环境为 64 位操作系统,JDK 为 1.8,JVM 为 HotSpot. 工具 JOL全称为Java Object Layout,是用来分析JVM中对象布局的工具,可以在运行时计算某个 ...

  9. 使用JOL工具直接查看出java对象大小

    JOL全称为Java Object Layout,是用来分析JVM中对象布局的工具,它可以帮我们在运行时计算某个对象的大小. 引入JOL依赖,如下: <!-- https://mvnreposi ...

最新文章

  1. 数据预处理(完整步骤)
  2. 牛客网:为什么不能将实数作为 HashMap 的 key?
  3. 没有c语言基础可以学python吗-零基础学Python之前需要学c语言吗
  4. ASP.NET Core 5 在IIS,Nginx,Caddy下的性能测试
  5. 使用fping 查看局域网中有哪些ip
  6. Nginx+Tomcat动静分离
  7. socket 怎么设置心跳判断连接
  8. Protobuf学习 - 入门(转)
  9. 跟据URL来实现WebService
  10. Android消除Toast延迟显示
  11. Unable to find setter method for attribute: [commandName]
  12. 343.微生物组研究写作的一般思路
  13. [Python ]个税计算
  14. python父亲节祝福_关于父亲节的祝福语大全(27句),暖心的句子
  15. 几个维度带你了解什么是聚合支付
  16. 实验3 SQL的复杂多表查询以及视图
  17. 零基础免费通过hexo+github快速搭建个人博客(超详细图解+B站视频讲解资源)
  18. ios 模拟器如何模拟多点触控
  19. HTML5训练营,360奇舞特训营(一):HTML
  20. 在微型计算机内存储器中,不能用指令修改其存储内容的部分是,在微型计算机内存储器中,不能用指令修改其存储内容的部分是______。...

热门文章

  1. spring boot redis 广播消息
  2. C语言中scanf函数用法详解
  3. java 常用的数据库连接池,java通过数据库连接池的方式
  4. 【 RA4M2开发板环境搭建之串口下载1】
  5. Windows 7 蓝屏代码大全 蓝屏全攻略
  6. 前端导入Excel,后台接收并处理(超详细!)
  7. C/C++编程:成员函数
  8. linux 3.4.39 arm,x6818_Smart_Home
  9. xml文件的生成和下载
  10. K8S之Scheduler调度器