Java では、オブジェクトが割り当てられている間に使用するメモリの正確な量を把握したいと考えています。
コンストラクターとメジャーを呼び出すだけでは、コンストラクター中に他のオブジェクトが割り当てられる可能性があるため、機能しません。また、特定の VM で使用されているメモリをリアルタイムで計算する方法を使用することを好みます。これは標準の VM ではない可能性があるため、フィールドを数えて適切な推測を行うだけでは十分ではありません。
とにかく、これまでのところ、見つかった を使用して、他の割り当てなしでオブジェクトを作成できることがnewConstructorForSerialization
わかりましたsun.reflect.ReflectionFactory
。
これは機能しますが、どういうわけか、newInstance の呼び出しは、予想よりも多くの 1 ブロックのメモリを割り当てます。
たとえば、クラス
public class a {
Integer a;
}
と
public class b {
Integer b = new Integer(12345);
}
どちらも同じ結果になるはずです。この場合、デフォルト VM で Java 7 を使用して 16 バイト。
ただし、私のコードでは 32 バイト (常に予想よりも 16 バイト多い) が返されます。結果から 16 を削除することでこれを補うことができますが、常に追加のブロックが割り当てられることを 100% 確認する必要があります。正確な量よりも、メモリ使用量の上限を知ることが重要です。したがって、このブロックが常に追加されると 100% 確信している場合にのみ、結果から 16 を差し引いても安全です。
私のコード: ( -XX:-UseTLAB VM 引数で実行)
import java.lang.reflect.Constructor;
import sun.reflect.ReflectionFactory;
public class test {
public static void main(String[] args) throws Exception {
prepare(a.class, Object.class);
System.out.println(memUse());
System.out.println(memUseSimple());
}
private static long memUseSimple() {
long start = Runtime.getRuntime().freeMemory();
a a = new a();
return start - Runtime.getRuntime().freeMemory();
}
private static long memUse() throws Exception {
Object o0 = intConstr.newInstance();
long start = Runtime.getRuntime().freeMemory();
Object o1 = intConstr.newInstance();
return start - Runtime.getRuntime().freeMemory() - 16;
}
private static Constructor<?> intConstr;
private static void prepare(Class<?> clazz, Class<?> parent) throws Exception {
intConstr = ReflectionFactory.getReflectionFactory()
.newConstructorForSerialization(clazz,
parent.getDeclaredConstructor());
return;
}
}
編集:明確にするために:呼び出しの16バイトのオーバーヘッドを差し引く必要がある理由を知りたいのですが、intConstr.newInstance()
このオーバーヘッドが常に同じ(または少なくとも16バイト以上)であると100%確信できる場合。
上記のコードで a を b に置き換えても、 の結果として 16 が得られますが、 は得られmemUse()
ませんmemUseSimple()
。気にするだけですmemUse()
が、比較として簡単な方法を追加しました。
intConstr.newInstance()
別の VM で異なるオーバーヘッドが発生する可能性があることはわかっています。これは重要ではありません。現在の VM で 16 バイトのオーバーヘッドが発生する場合、(このランタイム中に) 常に 16 バイトのオーバーヘッドが発生するかどうかを知る必要がありますか? また、このオーバーヘッドはただと比較してどこから来るのnew a()
でしょうか?