今天没事看精华区,发现去年有人讨论java的sizeof。结论好想是没什么好办法。
上面的地址先讨论了一下java中没有sizeof的必要,然后给了一段实现sizeof的代码。
In previous issues we've mentioned that Java(tm) has no sizeof() operator
like C/C++. With uniform sizes for primitive data types, and a different
style of memory allocation, the need for sizeof() really isn't there. And
it's hard to define what sizeof() would mean anyway, given that an object
may not contain other objects, but only references to them.
But it's interesting to experiment with the 1.1 reflection feature and see
whether a method can be devised that will return useful information about
object sizes.
The Sizeof class below tries to do this, for a passed-in data structure.
It walks the structure and tallies up the total size in bytes. It ignores
alignment and packing issues and hidden fields in structures, and assumes
a boolean is of size 1 and a reference of size 4 (reference sizes may vary
; for example SZ_REF might be 8 on a machine with 64-bit pointers).
It does not count static data members of class instances, but does include
members inherited/implemented from superclasses and interfaces. It does
not follow references in object instances or in arrays, except for the case
of a multi-dimensional array, where the reference is to another array.
Included are some tests that illustrate what results are expected in given
cases.
import java.lang.reflect.*;
class test_Class1 {
private int a1;
public byte a2;
protected char a3[];
static byte a33;
}
class test_Class2 extends test_Class1 {
static float a33;
byte a3;
short a4;
double a5[] = new double[10];
}
class test_Class3 extends test_Class2 {
boolean a4;
static int a44;
char a5;
long a6;
}
interface test_Class4 {
public byte x = 1;
}
interface test_Class5 extends test_Class4 {
public int x = 2;
}
class test_Class6 {
public double x;
}
class test_Class7 extends test_Class6 implements test_Class5 {
char x[] = null;
}
public class Sizeof {
private static final int SZ_REF = 4;
public static int sizeof(boolean b)
{
return 1;
}
public static int sizeof(byte b)
{
return 1;
}
public static int sizeof(char c)
{
return 2;
}
public static int sizeof(short s)
{
return 2;
}
public static int sizeof(int i)
{
return 4;
}
public static int sizeof(long l)
{
return 8;
}
public static int sizeof(float f)
{
return 4;
}
public static int sizeof(double d)
{
return 8;
}
private static int size_inst(Class c)
{
Field flds[] = c.getDeclaredFields();
int sz = 0;
for (int i = 0; i < flds.length; i++) {
Field f = flds[i];
if (!c.isInterface() &&
(f.getModifiers() & Modifier.STATIC) != 0)
continue;
sz += size_prim(f.getType());
}
if (c.getSuperclass() != null)
sz += size_inst(c.getSuperclass());
Class cv[] = c.getInterfaces();
for (int i = 0; i < cv.length; i++)
sz += size_inst(cv[i]);
return sz;
}
private static int size_prim(Class t)
{
if (t == Boolean.TYPE)
return 1;
else if (t == Byte.TYPE)
return 1;
else if (t == Character.TYPE)
return 2;
else if (t == Short.TYPE)
return 2;
else if (t == Integer.TYPE)
return 4;
else if (t == Long.TYPE)
return 8;
else if (t == Float.TYPE)
return 4;
else if (t == Double.TYPE)
return 8;
else if (t == Void.TYPE)
return 0;
else
return SZ_REF;
}
private static int size_arr(Object obj, Class c)
{
Class ct = c.getComponentType();
int len = Array.getLength(obj);
if (ct.isPrimitive()) {
return len * size_prim(ct);
}
else {
int sz = 0;
for (int i = 0; i < len; i++) {
sz += SZ_REF;
Object obj2 = Array.get(obj, i);
if (obj2 == null)
continue;
Class c2 = obj2.getClass();
if (!c2.isArray())
continue;
sz += size_arr(obj2, c2);
}
return sz;
}
}
public static int sizeof(Object obj)
{
if (obj == null)
return 0;
Class c = obj.getClass();
if (c.isArray())
return size_arr(obj, c);
else
return size_inst(c);
}
private static void err(String s)
{
System.err.println("*** " + s + " ***");
}
private static void test()
{
if (sizeof(null) != 0)
err("null");
if (sizeof(true) != 1)
err("boolean");
if (sizeof((byte)37) != 1)
err("byte");
if (sizeof('x') != 2)
err("char");
if (sizeof((short)37) != 2)
err("short");
if (sizeof(37) != 4)
err("int");
if (sizeof(37L) != 8)
err("long");
if (sizeof(37.0f) != 4)
err("float");
if (sizeof(37.0) != 8)
err("double");
if (sizeof(new boolean[0]) != 0)
err("boolean[0]");
if (sizeof(new byte[10]) != 10)
err("byte[10]");
if (sizeof(new char[10][10]) != 200 + 10 * SZ_REF)
err("char[10][10]");
if (sizeof(new short[10][11][12]) != 2640 +
120 * SZ_REF)
err("short[10][11][12]");
if (sizeof(new int[0][10]) != 0)
err("int[0][10]");
if (sizeof(new String[100]) != 100 * SZ_REF)
err("String[100]");
if (sizeof(new String[10][10]) != 110 * SZ_REF)
err("String[10][10]");
Object ov[] = new Object[3];
ov[0] = new byte[10];
ov[2] = new double[10];
if (sizeof(ov) != 90 + 3 * SZ_REF)
err("Object[3]");
String sv[] = new String[10];
for (int i = 0; i < 10; i++)
sv[i] = new String();
if (sizeof(sv) != 10 * SZ_REF)
err("String[10]");
if (sizeof(new Object()) != 0)
err("Object");
if (sizeof(new Integer(37)) != 4)
err("Integer(37)");
if (sizeof(new test_Class1()) != 5 + SZ_REF)
err("test_Class1");
if (sizeof(new test_Class2()) != 8 + 2 * SZ_REF)
err("test_Class2");
if (sizeof(new test_Class3()) != 19 + 2 * SZ_REF)
err("test_Class3");
if (sizeof(new test_Class7()) != 13 + SZ_REF)
err("test_Class7");
}
public static void main(String args[])
{
test();
}
}
上面的地址先讨论了一下java中没有sizeof的必要,然后给了一段实现sizeof的代码。
In previous issues we've mentioned that Java(tm) has no sizeof() operator
like C/C++. With uniform sizes for primitive data types, and a different
style of memory allocation, the need for sizeof() really isn't there. And
it's hard to define what sizeof() would mean anyway, given that an object
may not contain other objects, but only references to them.
But it's interesting to experiment with the 1.1 reflection feature and see
whether a method can be devised that will return useful information about
object sizes.
The Sizeof class below tries to do this, for a passed-in data structure.
It walks the structure and tallies up the total size in bytes. It ignores
alignment and packing issues and hidden fields in structures, and assumes
a boolean is of size 1 and a reference of size 4 (reference sizes may vary
; for example SZ_REF might be 8 on a machine with 64-bit pointers).
It does not count static data members of class instances, but does include
members inherited/implemented from superclasses and interfaces. It does
not follow references in object instances or in arrays, except for the case
of a multi-dimensional array, where the reference is to another array.
Included are some tests that illustrate what results are expected in given
cases.
import java.lang.reflect.*;
class test_Class1 {
private int a1;
public byte a2;
protected char a3[];
static byte a33;
}
class test_Class2 extends test_Class1 {
static float a33;
byte a3;
short a4;
double a5[] = new double[10];
}
class test_Class3 extends test_Class2 {
boolean a4;
static int a44;
char a5;
long a6;
}
interface test_Class4 {
public byte x = 1;
}
interface test_Class5 extends test_Class4 {
public int x = 2;
}
class test_Class6 {
public double x;
}
class test_Class7 extends test_Class6 implements test_Class5 {
char x[] = null;
}
public class Sizeof {
private static final int SZ_REF = 4;
public static int sizeof(boolean b)
{
return 1;
}
public static int sizeof(byte b)
{
return 1;
}
public static int sizeof(char c)
{
return 2;
}
public static int sizeof(short s)
{
return 2;
}
public static int sizeof(int i)
{
return 4;
}
public static int sizeof(long l)
{
return 8;
}
public static int sizeof(float f)
{
return 4;
}
public static int sizeof(double d)
{
return 8;
}
private static int size_inst(Class c)
{
Field flds[] = c.getDeclaredFields();
int sz = 0;
for (int i = 0; i < flds.length; i++) {
Field f = flds[i];
if (!c.isInterface() &&
(f.getModifiers() & Modifier.STATIC) != 0)
continue;
sz += size_prim(f.getType());
}
if (c.getSuperclass() != null)
sz += size_inst(c.getSuperclass());
Class cv[] = c.getInterfaces();
for (int i = 0; i < cv.length; i++)
sz += size_inst(cv[i]);
return sz;
}
private static int size_prim(Class t)
{
if (t == Boolean.TYPE)
return 1;
else if (t == Byte.TYPE)
return 1;
else if (t == Character.TYPE)
return 2;
else if (t == Short.TYPE)
return 2;
else if (t == Integer.TYPE)
return 4;
else if (t == Long.TYPE)
return 8;
else if (t == Float.TYPE)
return 4;
else if (t == Double.TYPE)
return 8;
else if (t == Void.TYPE)
return 0;
else
return SZ_REF;
}
private static int size_arr(Object obj, Class c)
{
Class ct = c.getComponentType();
int len = Array.getLength(obj);
if (ct.isPrimitive()) {
return len * size_prim(ct);
}
else {
int sz = 0;
for (int i = 0; i < len; i++) {
sz += SZ_REF;
Object obj2 = Array.get(obj, i);
if (obj2 == null)
continue;
Class c2 = obj2.getClass();
if (!c2.isArray())
continue;
sz += size_arr(obj2, c2);
}
return sz;
}
}
public static int sizeof(Object obj)
{
if (obj == null)
return 0;
Class c = obj.getClass();
if (c.isArray())
return size_arr(obj, c);
else
return size_inst(c);
}
private static void err(String s)
{
System.err.println("*** " + s + " ***");
}
private static void test()
{
if (sizeof(null) != 0)
err("null");
if (sizeof(true) != 1)
err("boolean");
if (sizeof((byte)37) != 1)
err("byte");
if (sizeof('x') != 2)
err("char");
if (sizeof((short)37) != 2)
err("short");
if (sizeof(37) != 4)
err("int");
if (sizeof(37L) != 8)
err("long");
if (sizeof(37.0f) != 4)
err("float");
if (sizeof(37.0) != 8)
err("double");
if (sizeof(new boolean[0]) != 0)
err("boolean[0]");
if (sizeof(new byte[10]) != 10)
err("byte[10]");
if (sizeof(new char[10][10]) != 200 + 10 * SZ_REF)
err("char[10][10]");
if (sizeof(new short[10][11][12]) != 2640 +
120 * SZ_REF)
err("short[10][11][12]");
if (sizeof(new int[0][10]) != 0)
err("int[0][10]");
if (sizeof(new String[100]) != 100 * SZ_REF)
err("String[100]");
if (sizeof(new String[10][10]) != 110 * SZ_REF)
err("String[10][10]");
Object ov[] = new Object[3];
ov[0] = new byte[10];
ov[2] = new double[10];
if (sizeof(ov) != 90 + 3 * SZ_REF)
err("Object[3]");
String sv[] = new String[10];
for (int i = 0; i < 10; i++)
sv[i] = new String();
if (sizeof(sv) != 10 * SZ_REF)
err("String[10]");
if (sizeof(new Object()) != 0)
err("Object");
if (sizeof(new Integer(37)) != 4)
err("Integer(37)");
if (sizeof(new test_Class1()) != 5 + SZ_REF)
err("test_Class1");
if (sizeof(new test_Class2()) != 8 + 2 * SZ_REF)
err("test_Class2");
if (sizeof(new test_Class3()) != 19 + 2 * SZ_REF)
err("test_Class3");
if (sizeof(new test_Class7()) != 13 + SZ_REF)
err("test_Class7");
}
public static void main(String args[])
{
test();
}
}