我想知道任何簡單的方法來檢索一個Java對象的大小?此外,無論如何,以獲得在C++ sizeof運算符類的大小?有沒有簡單的方法來獲取java對象的大小?
回答
有一個opensource java.SizeOf project決定了您的任何Java對象在內存中的大小。
Instrumentation接口有一個getObjectSize()方法。
但是,這隻會給你對象本身的大小,而不是它的組件子對象。舉例來說,它會告訴你所有的String
對象都是相同的大小。
另一個問題是對象的大小實際上可以自發地改變。例如,如果您獲得對象的標識哈希碼並且它在GC週期中存活,則其大小將增加(至少)4個字節以存儲標識哈希碼值。
發現「的對象」的大小的問題是,它是不可能的一般效用類/方法肯定知道其中的任意對象的抽象邊界。即使像String類一樣簡單,也存在問題。 (考慮使用Java中6 substring(...)
創建String對象你可以在char[] value
對象的this
的一部分,還是原來的字符串的一部分,或兩者兼而有之?這是什麼意思爲相應對象的大小?)
因此,像net.sourceforge.sizeof
這樣的東西不可能提供空間使用的完全準確的計算。
當你的程序運行,拿到另一個終端窗口,運行:
jmap -histo <process id of the java instance you want to debug>
在它給人的數量和類對象實例的總大小的輸出。例如,3 72 java.util.Date
表示在內存中有3個Date對象,每個對象需要24個字節。如果相關部分滾動太快,您可能需要將輸出傳輸到文件或其他東西。
或者,(多)更詳細,運行:
jmap -dump:format=b,file=heap.bin <processid>
jhat heap.bin
然後打開http://localhost:7000。您可以瀏覽瀏覽器中堆上的對象。
更多信息:
http://docs.oracle.com/javase/6/docs/technotes/tools/share/jmap.html
http://docs.oracle.com/javase/6/docs/technotes/tools/share/jhat.html
我認爲它總是得到的方式四捨五入爲8,在Sun/Oracle的JVM,即使對象是12個字節,它會內存中有16個。
使用Unsafe
類從sun.misc
您可以獲得字段偏移量。因此,根據處理器體系結構考慮對象堆對齊並計算最大字段偏移量,可以測量Java對象的大小。在下面的示例中,我使用輔助類UtilUnsafe
來獲取對sun.misc.Unsafe
對象的引用。
private static final int NR_BITS = Integer.valueOf(System.getProperty("sun.arch.data.model"));
private static final int BYTE = 8;
private static final int WORD = NR_BITS/BYTE;
private static final int MIN_SIZE = 16;
public static int sizeOf(Class src){
//
// Get the instance fields of src class
//
List<Field> instanceFields = new LinkedList<Field>();
do{
if(src == Object.class) return MIN_SIZE;
for (Field f : src.getDeclaredFields()) {
if((f.getModifiers() & Modifier.STATIC) == 0){
instanceFields.add(f);
}
}
src = src.getSuperclass();
}while(instanceFields.isEmpty());
//
// Get the field with the maximum offset
//
long maxOffset = 0;
for (Field f : instanceFields) {
long offset = UtilUnsafe.UNSAFE.objectFieldOffset(f);
if(offset > maxOffset) maxOffset = offset;
}
return (((int)maxOffset/WORD) + 1)*WORD;
}
class UtilUnsafe {
public static final sun.misc.Unsafe UNSAFE;
static {
Object theUnsafe = null;
Exception exception = null;
try {
Class<?> uc = Class.forName("sun.misc.Unsafe");
Field f = uc.getDeclaredField("theUnsafe");
f.setAccessible(true);
theUnsafe = f.get(uc);
} catch (Exception e) { exception = e; }
UNSAFE = (sun.misc.Unsafe) theUnsafe;
if (UNSAFE == null) throw new Error("Could not obtain access to sun.misc.Unsafe", exception);
}
private UtilUnsafe() { }
}
確實有可能獲得對象大小,因爲某個類的對象只是一個固定大小的內存塊。我編寫了下面的代碼來計算一個對象的保留大小。它還提供了一種像C++中的'sizeof'這樣的方法。它準備好運行並且不依賴於任何東西。你可以複製並嘗試它!
public class ObjectSizer {
public static final Unsafe us = getUnsafe();
public static boolean useCompressedOops = true;
public static int retainedSize(Object obj) {
return retainedSize(obj, new HashMap<Object, Object>());
}
private static int retainedSize(Object obj, HashMap<Object, Object> calculated) {
try {
if (obj == null)
throw new NullPointerException();
calculated.put(obj, obj);
Class<?> cls = obj.getClass();
if (cls.isArray()) {
int arraysize = us.arrayBaseOffset(cls) + us.arrayIndexScale(cls) * Array.getLength(obj);
if (!cls.getComponentType().isPrimitive()) {
Object[] arr = (Object[]) obj;
for (Object comp : arr) {
if (comp != null && !isCalculated(calculated, comp))
arraysize += retainedSize(comp, calculated);
}
}
return arraysize;
} else {
int objectsize = sizeof(cls);
for (Field f : getAllNonStaticFields(obj.getClass())) {
Class<?> fcls = f.getType();
if (fcls.isPrimitive())
continue;
f.setAccessible(true);
Object ref = f.get(obj);
if (ref != null && !isCalculated(calculated, ref)) {
int referentSize = retainedSize(ref, calculated);
objectsize += referentSize;
}
}
return objectsize;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static int sizeof(Class<?> cls) {
if (cls == null)
throw new NullPointerException();
if (cls.isArray())
throw new IllegalArgumentException();
if (cls.isPrimitive())
return primsize(cls);
int lastOffset = Integer.MIN_VALUE;
Class<?> lastClass = null;
for (Field f : getAllNonStaticFields(cls)) {
if (Modifier.isStatic(f.getModifiers()))
continue;
int offset = (int) us.objectFieldOffset(f);
if (offset > lastOffset) {
lastOffset = offset;
lastClass = f.getClass();
}
}
if (lastOffset > 0)
return modulo8(lastOffset + primsize(lastClass));
else
return 16;
}
private static Field[] getAllNonStaticFields(Class<?> cls) {
if (cls == null)
throw new NullPointerException();
List<Field> fieldList = new ArrayList<Field>();
while (cls != Object.class) {
for (Field f : cls.getDeclaredFields()) {
if (!Modifier.isStatic(f.getModifiers()))
fieldList.add(f);
}
cls = cls.getSuperclass();
}
Field[] fs = new Field[fieldList.size()];
fieldList.toArray(fs);
return fs;
}
private static boolean isCalculated(HashMap<Object, Object> calculated, Object test) {
Object that = calculated.get(test);
return that != null && that == test;
}
private static int primsize(Class<?> cls) {
if (cls == byte.class)
return 1;
if (cls == boolean.class)
return 1;
if (cls == char.class)
return 2;
if (cls == short.class)
return 2;
if (cls == int.class)
return 4;
if (cls == float.class)
return 4;
if (cls == long.class)
return 8;
if (cls == double.class)
return 8;
else
return useCompressedOops ? 4 : 8;
}
private static int modulo8(int value) {
return (value & 0x7) > 0 ? (value & ~0x7) + 8 : value;
}
private static Unsafe getUnsafe() {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(Unsafe.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
System.out.println(retainedSize("Hello Leeeeeeeen"));
}
}
- 1. 有沒有簡單的方法來估計json對象的大小?
- 2. 有沒有簡單的方法來獲得python私有堆大小?
- 3. 有沒有簡單的方法來增加Map對象的值?
- 4. 有沒有一種簡單的方法來在沒有JavaScript的情況下在PHP中獲取圖像大小?
- 5. 有沒有簡單的方法來獲取日期?
- 6. 有沒有簡單的方法來獲取li:gt(-1)在jquery中?
- 7. 有沒有簡單的方法來覆蓋列表對象的方法__getitem__?
- 8. 有沒有一種簡單的方法來獲取objective-c/iPhone-OS中對象的創建者對象?
- 9. 簡單的方法來獲取Leaflet LayerGroup的大小?
- 10. KnockoutJS - 有沒有簡單的方法來覆蓋單個對象的observables?
- 11. 有沒有更簡單的方法來解析Java中的Android?
- 12. 有沒有簡單的方法來改變NSTableView的字體大小?
- 13. 有沒有一種簡單的方法來實現LINQ來與DataContext對象?
- 14. 有沒有更簡單的方法來寫這個(java)
- 15. 有沒有簡單的方法來在java中播放rtmp流?
- 16. astropy.io.votable - 有沒有簡單的方法來獲得VOTable PARAMeters?
- 17. 有沒有簡單的方法來獲得AspectJ輸出文件?
- 18. 有沒有簡單的方法(宏?)來告訴結構對齊?
- 19. 有沒有更簡單的方法來取消嵌套數組?
- 20. 有沒有簡單的方法來實現List列選取器?
- 21. 對象有一個相當簡單的請求沒有方法
- 22. Android:有沒有辦法獲得RemoteViews對象的大小?
- 23. 是否有一種簡單的方法來獲取Java中特定類的所有對象實例
- 24. 有沒有一種簡單的方法來獲取OpenGL中對象的深度(JOGL)
- 25. 有沒有簡單的方法來獲取當前狀態的狀態組或實際狀態對象?
- 26. 有沒有簡單的方法來獲取嵌套的兒童參考?
- 27. 有沒有一種簡單的方法來獲取URL中的URL
- 28. 有沒有簡單的方法來獲取基於給定路徑的folderID?
- 29. 有沒有一種簡單的方法來獲取Symfony中的ServerName?
- 30. 有沒有一些簡單的方法來獲取API V3中的map.fromLatLngToDivPixel?
http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object – NAVEED 2012-01-08 06:44:32
你可以更具體。你在談論java對象正在使用的內存大小嗎? – 2012-01-08 06:44:41
參見http://stackoverflow.com/questions/757300/programatically-calculate-memory-occupied-by-a-java-object-including-objects-it – user371320 2012-01-08 06:45:53