java计算对象的内存占用都有哪些方式,以及代码实例
时间: 2024-02-11 07:05:18 浏览: 160
Java中计算对象内存占用的方式主要有以下几种:
1. 使用Instrumentation API
Java提供了一个Instrumentation API,可以通过该API获取对象的大小。该API需要在JVM启动时进行注册,具体使用方法如下:
```java
import java.lang.instrument.Instrumentation;
public class ObjectSizeFetcher {
private static Instrumentation instrumentation;
public static void premain(String args, Instrumentation inst) {
instrumentation = inst;
}
public static long getObjectSize(Object obj) {
if (instrumentation == null) {
throw new IllegalStateException("Instrumentation is null");
}
return instrumentation.getObjectSize(obj);
}
}
```
在使用该API时,需要在JVM启动时添加如下参数:-javaagent:path/to/agent.jar,其中agent.jar是包含上述代码的jar包。
2. 使用Apache Commons Lang库
Apache Commons Lang库提供了一个SerializationUtils类,可以计算对象的大小。具体使用方法如下:
```java
import org.apache.commons.lang3.SerializationUtils;
public class ObjectSizeFetcher {
public static long getObjectSize(Object obj) {
byte[] data = SerializationUtils.serialize(obj);
return data.length;
}
}
```
需要注意的是,该方法需要将对象序列化为字节数组,因此可能会影响性能。
3. 使用自定义工具类
我们也可以自己编写一个工具类来计算对象的大小。具体实现方法如下:
```java
public class ObjectSizeFetcher {
private static final Unsafe UNSAFE = getUnsafe();
public static long getObjectSize(Object obj) {
if (obj == null) {
return 0;
}
Class<?> clazz = obj.getClass();
if (clazz.isArray()) {
int length = Array.getLength(obj);
long size = UNSAFE.arrayBaseOffset(clazz) + length * UNSAFE.arrayIndexScale(clazz);
return padSize(size);
} else {
long size = 0;
while (clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
if (!Modifier.isStatic(field.getModifiers())) {
size += getSize(field.getType());
}
}
clazz = clazz.getSuperclass();
}
return padSize(size);
}
}
private static long getSize(Class<?> clazz) {
if (clazz == boolean.class || clazz == byte.class) {
return 1;
} else if (clazz == char.class || clazz == short.class) {
return 2;
} else if (clazz == int.class || clazz == float.class) {
return 4;
} else if (clazz == long.class || clazz == double.class) {
return 8;
} else {
return getObjectSize(null);
}
}
private static long padSize(long size) {
return (size + 7) & ~7;
}
private static Unsafe getUnsafe() {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
```
该方法使用了Java的Unsafe类来获取对象的内存大小,因此需要注意安全问题。在使用该方法时,需要注意对象内部可能包含引用类型和数组等情况。
阅读全文