java new object 内存_如何通过理论方法计算java new ArrayList<Object>()对象的实际内存占用空间?...

我会建议不要对一个实际的JVM实现依赖于自己“理论计算对象布局”做假设。毕竟代码日新月异,如果不是每天都直接跟JVM内部实现打交道的话,自己的“理论”什么时候过时了或者哪里有个啥疏漏也难以察觉。

针对HotSpot VM,这种问题现在有超级方便的工具来解答了:发布在OpenJDK上的JOL(Java Object Layout),由Aleksey Shipilëv大大开发。

官网链接:OpenJDK: jol

这是我在Mac OS X上跑Oracle JDK8u101,关掉压缩指针得到的输出:

$ java -XX:-UseCompressedOops -Djol.tryWithSudo=true -jar ~/Downloads/jol-cli-0.6-full.jar internals java.util.ArrayList

objc[49091]: Class JavaLaunchHelper is implemented in both /Users/krismo/sdk/jdk1.8.0_101/Contents/Home/bin/java and /Users/krismo/sdk/jdk1.8.0_101/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.

# Running 64-bit HotSpot VM.

# Objects are 8 bytes aligned.

# Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

# Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

java.util.ArrayList object internals:

OFFSET SIZE TYPE DESCRIPTION VALUE

0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5)

4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)

8 4 (object header) f0 ad e9 23 (11110000 10101101 11101001 00100011) (602516976)

12 4 (object header) 02 00 00 00 (00000010 00000000 00000000 00000000) (2)

16 4 int AbstractList.modCount 0

20 4 (alignment/padding gap) N/A

24 4 int ArrayList.size 0

28 4 (alignment/padding gap) N/A

32 8 Object[] ArrayList.elementData []

Instance size: 40 bytes

Space losses: 8 bytes internal + 0 bytes external = 8 bytes total其中,关掉压缩指针时的对象头有_mark和_klass两个字段,每个都是8字节;

然后在类继承边界上(ArrayList继承AbstractList)也有对齐带来的padding。这个例子中就是位于offset +20的那4字节。题主没想明白的大概就是这里。

在4字节宽的字段与8字节宽的字段之间也可能会有对齐带来的padding(因为8字节宽的字段需要8字节对齐,而前面的4字节宽字段只需要4字节对齐),这就是位于offset +28的那4字节。

就这样。

本来在继承边界上的padding也可以用来分配给派生类的合适宽度的字段用,但HotSpot VM并没有这样做。算是个缺陷吧。

HotSpot VM在计算派生类的字段的布局时,直接先问基类的实例大小有多大(但却没有问基类实例的末尾有没有padding),然后从基类的实例大小之后开始计算派生类字段的偏移量。所以基类末尾有padding的话…就浪费了。

顺便演示一下基类AbstractList的情况吧:

$ java -XX:-UseCompressedOops -Djol.tryWithSudo=true -jar ~/Downloads/jol-cli-0.6-full.jar internals java.util.AbstractList

objc[49134]: Class JavaLaunchHelper is implemented in both /Users/krismo/sdk/jdk1.8.0_101/Contents/Home/bin/java and /Users/krismo/sdk/jdk1.8.0_101/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.

# Running 64-bit HotSpot VM.

# Objects are 8 bytes aligned.

# Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

# Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

VM fails to invoke the default constructor, falling back to class-only introspection.

java.util.AbstractList object internals:

OFFSET SIZE TYPE DESCRIPTION VALUE

0 16 (object header) N/A

16 4 int AbstractList.modCount N/A

20 4 (loss due to the next object alignment)

Instance size: 24 bytes

Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一种可能的实现方式: 1. 使用Jackson库进行Json解析,它支持流式处理,不会一次性将整个Json字符串读入内存。 2. 采用多线程处理,将大量Json字符串分割成若干个小段,每个线程处理一段,避免单线程处理过多Json字符串导致CPU占用过高。 3. 使用内存池技术,重复利用已经分配的内存空间,避免频繁的内存分配和释放,从而减少内存占用。 以下是代码示例: ```java import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class JsonToObjectConverter { private static final ObjectMapper mapper = new ObjectMapper(); /** * 将大量Json字符串转换为对象集合 * @param jsonList Json字符串列表 * @return 对象集合 */ public List<Object> convert(List<String> jsonList) { List<Object> result = new ArrayList<>(); ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); try { for (String json : jsonList) { executorService.execute(() -> { try { JsonParser parser = mapper.getFactory().createParser(json); Object object = mapper.readValue(parser, Object.class); synchronized (result) { result.add(object); } } catch (IOException e) { e.printStackTrace(); } }); } } finally { executorService.shutdown(); } return result; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值