http://www.dewen.net.cn/q/6120/如何获取Java对象的大小
2016-03-10 16:13
459 查看
http://www.dewen.net.cn/q/6120/如何获取Java对象的大小
kenvi
1 票
kenvi 2078
在C或者C++里经常会通过sizeof来计算一个对象所占空间的大小,但是对于java对象,如何获得其大小呢?
评论 (1) • 举报 (0) • 分享 • 链接 • 2012-09-26
1 http://www.javaworld.com/javaworld/javaqa/2003-12/02-qa-1226-sizeof.html?page=2 – Darcy 2012-09-27
添加评论...
brayden认证专家
0 票
brayden6562
用Unsafe, 主要代码引自: http://mishadoff.github.io/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
@Test
public void testea() throws Exception{
System.out.println(sizeOf1(new Object()));
System.out.println(sizeOf1(new TestTesteTestB()));
}
private long sizeOf(Object o) throws Exception {
Unsafe u = getUnsafe();
HashSet<Field> fields = new HashSet<Field>();
Class c = o.getClass();
while (c != Object.class) {
for (Field f : c.getDeclaredFields()) {
if ((f.getModifiers() & Modifier.STATIC) == 0) {
fields.add(f);
}
}
c = c.getSuperclass();
}
long maxSize = 0;
for (Field f : fields) {
long offset = u.objectFieldOffset(f);
System.out.println("sdfsd"+offset);
if (offset > maxSize) {
maxSize = offset;
}
}
return ((maxSize / 8) + 1) * 8;
}
private Unsafe getUnsafe() throws Exception {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(null);
}
我的运行结果:
8
32
看了一些资料, 这里说一下我的理解:
1). Java对象实例大小都是8的倍数;
2). 开头为 4字节java对象头, 4字节为 类对象(Klass) 的引用; 然后是对象 实例成员(field);
3). 对象 实例成员的存储, java不一定按照类定义的顺序, 为了优化存储空间, 会做重排;
4). 为了对齐, 可能会做padding.
这样, 上面的sizeof中, 先拿到偏移对大的那个field, 再做padding((maxSize / 8) + 1) * 8;); 从而拿到对象的大小. Object对象为8个字节, 这已经是最小的了(因为其没有额外的field定义).
kenvi
1 票
kenvi 2078
在C或者C++里经常会通过sizeof来计算一个对象所占空间的大小,但是对于java对象,如何获得其大小呢?
评论 (1) • 举报 (0) • 分享 • 链接 • 2012-09-26
1 http://www.javaworld.com/javaworld/javaqa/2003-12/02-qa-1226-sizeof.html?page=2 – Darcy 2012-09-27
添加评论...
brayden认证专家
0 票
brayden6562
用Unsafe, 主要代码引自: http://mishadoff.github.io/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
@Test
public void testea() throws Exception{
System.out.println(sizeOf1(new Object()));
System.out.println(sizeOf1(new TestTesteTestB()));
}
private long sizeOf(Object o) throws Exception {
Unsafe u = getUnsafe();
HashSet<Field> fields = new HashSet<Field>();
Class c = o.getClass();
while (c != Object.class) {
for (Field f : c.getDeclaredFields()) {
if ((f.getModifiers() & Modifier.STATIC) == 0) {
fields.add(f);
}
}
c = c.getSuperclass();
}
long maxSize = 0;
for (Field f : fields) {
long offset = u.objectFieldOffset(f);
System.out.println("sdfsd"+offset);
if (offset > maxSize) {
maxSize = offset;
}
}
return ((maxSize / 8) + 1) * 8;
}
private Unsafe getUnsafe() throws Exception {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(null);
}
我的运行结果:
8
32
看了一些资料, 这里说一下我的理解:
1). Java对象实例大小都是8的倍数;
2). 开头为 4字节java对象头, 4字节为 类对象(Klass) 的引用; 然后是对象 实例成员(field);
3). 对象 实例成员的存储, java不一定按照类定义的顺序, 为了优化存储空间, 会做重排;
4). 为了对齐, 可能会做padding.
这样, 上面的sizeof中, 先拿到偏移对大的那个field, 再做padding((maxSize / 8) + 1) * 8;); 从而拿到对象的大小. Object对象为8个字节, 这已经是最小的了(因为其没有额外的field定义).
相关文章推荐
- OSI七层与TCP/IP五层网络架构详解
- OSI七层与TCP/IP五层网络架构详解
- 谷歌发布的首款基于HTTP/2和protobuf的RPC框架:GRPC
- wireshark 抓包 实例分析TCP三次握手过程
- TCP/IP/UDP/ICMP/ARP/ethernet 各种协议头部结构体
- httpclient https
- TCP/IP三次握手与四次挥手
- http://developer.51cto.com/art/201104/255729.htm
- httpclient Invalid use of SingleClientConnManager: connection still alloc
- Java HttpURLConnection超时问题
- Windows 下单机最大TCP连接数
- HttpFox: HTTP 监视及分析利器
- HttpClient 4.1 post 继续访问 重定向,301,302 的url
- 谷歌chrome浏览器和火狐firefox浏览器自带http抓包工具和请求模拟插件
- HttpsURLConnection
- HttpClient4.X Invalid use of SingleClientConnManager: connection still allocated
- 使用 HttpClient 4 进行文件上传
- 【网络流+可持久化线段树】[UOJ#77/BZOJ3218]A+B Problem
- http://www.dewen.net.cn/q/14879/搜索引擎结果自动跳转
- http://www.dewen.net.cn/q/14665/个人感觉用二分法最完美的,需要操作系统支持随机读取指定一行的数据,貌似现在还不行,江湖救急呀