函数的基本类型存储
函数的引用类型存储
分析String所占用的字节:
jdk1.8String的对象成员:
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
首先String是一个类
我们String a=new String(“aaa”);就会在堆中开辟内存
String a=“aaa”;会在方法区的常量池里开辟内存。
String a=new String(“aaa”);
UseCompressedOops默认是开启的>>>>>>>>>
在网上找了一个包,可以查看虚拟机状态,以及对象信息。
它给出的答案明显是48(一般内存的使用都是8字节的倍数,不够八字节自动填充为8字节倍数)
对象自己开销24字节:
12对象头+4存char数组指针+4存int类型的hash+4字节填充=24
实例化开销24字节:(其实就是实例化出来一个char数组)
数组是一个对象12个字节的对象头+4字节的数组长度存取+一个字符占用2字节*3个‘a’=22+2(字节自动补齐)
做一个小例子吧
public class Person {
private int a;
}
Person p=new Person();
此时系统为这个新对象开辟多少内存
我自己理解:
8字节对象头+4字节引用指针(p)+4字节变量a的开销=16
和我的期望是一样的12字节的对象头+4字节a变量的所占内存
计算对象占用内存的程序(从别人的CSDN看到的,也是从github上弄下来的,一个国外大佬写的)
需要去仓库下载一个包:
import org.openjdk.jol.vm.VirtualMachine;
import org.openjdk.jol.vm.VM;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.lang.*;
public class ObjectSize {
private final VirtualMachine vm;
private final Set<Object> visited;
private final Object[] roots;
public ObjectSize(Object... roots) {
this.roots = roots;
this.visited = Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>());
this.vm = VM.current();
}
public long calculateSize() {
long size = 0;
List<Object> curLayer = new ArrayList<Object>();
List<Object> newLayer = new ArrayList<Object>();
for (Object root : roots) {
visited.add(root);
size += size(root);
curLayer.add(root);
}
while (!curLayer.isEmpty()) {
newLayer.clear();
for (Object next : curLayer) {
for (Object ref : peelReferences(next)) {
if (visited.add(ref)) {
size += size(ref);
newLayer.add(ref);
}
}
}
curLayer.clear();
curLayer.addAll(newLayer);
}
return size;
}
private long size(Object obj) {
return obj != null ? vm.sizeOf(obj) : 0;
}
private static List<Object> peelReferences(Object o) {
if (o == null) {
// Nothing to do here
return Collections.emptyList();
}
if (o.getClass().isArray() && o.getClass().getComponentType().isPrimitive()) {
// Nothing to do here
return Collections.emptyList();
}
List<Object> result = new ArrayList<Object>();
if (o.getClass().isArray()) {
for (Object e : (Object[]) o) {
if (e != null) {
result.add(e);
}
}
} else {
for (Field f : getAllReferences(o.getClass())) {
try {
f.setAccessible(true);
} catch (Exception e) {
// Access denied
result.add(null);
continue;
}
try {
Object e = f.get(o);
if (e != null) {
result.add(e);
}
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
return result;
}
private static Collection<Field> getAllReferences(Class<?> klass) {
List<Field> results = new ArrayList<Field>();
for (Field f : klass.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers()))
continue;
if (f.getType().isPrimitive())
continue;
results.add(f);
}
Class<?> superKlass = klass;
while ((superKlass = superKlass.getSuperclass()) != null) {
for (Field f : superKlass.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers()))
continue;
if (f.getType().isPrimitive())
continue;
results.add(f);
}
}
return results;
}
public static long sizeOf(Object obj) {
return new ObjectSize(obj).calculateSize();
}
}
扩展(不用国外大佬程序 我们去看对象信息依然能计算出来对象内存)
// 查看虚拟机信息
System.out.println(VM.current().details());
// 查看对象信息
System.out.println(ClassLayout.parseInstance(p).toPrintable());