java 计算sizeof,以及校验和

来源:互联网 发布:黑岩集团知乎 编辑:程序博客网 时间:2024/06/05 04:15
package com.push.pojo;import java.lang.reflect.Field;import java.lang.reflect.Modifier;import sun.misc.Unsafe;@SuppressWarnings("restriction")public class CPPSizeof {public static final int OBJ_BASIC_LEN = 8 * 8;public static final int ARRAY_BASIC_LEN = 12 * 8;public static final int OBJ_REF_LEN = 4 * 8;public static final int ALIGN = 8 * 8;private static Unsafe UNSAFE;static {try {Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");theUnsafe.setAccessible(true);UNSAFE = (Unsafe) theUnsafe.get(null);} catch (Exception e) {e.printStackTrace();}}/** * 原始类型的种类,以及每个类型所占空间,单位为bit *  * @author Administrator * */private enum PType {布尔(8)/* Java语言规定是1个bit */, 字节(8), 字符(16), 短整(16), 整形(32), 浮点(32), 长整(64), 双精(64);private int bits;private PType(int bits) {this.bits = bits;}public int getBits() {return bits;}}/** * 计算obj对象在虚拟机中所占的内存,单位为bit。 如果isPapa为true,则表明计算的是obj对象父类定义的属性。 * * @param obj * @param clazz * @param isPapa * @return */private static int getObjBits(Object obj, Class clazz, boolean isPapa) {int bits = 0;if (obj == null) {return bits;}bits += OBJ_BASIC_LEN;if (isPapa) {bits = 0;}Field[] fields = clazz.getDeclaredFields();if (fields != null) {for (Field field : fields) {// 静态属性不参与计算if (Modifier.isStatic(field.getModifiers())) {// System.out.println("static " + field.getName());continue;}Class c = field.getType();if (c == boolean.class) {bits += PType.布尔.getBits();} else if (c == byte.class) {bits += PType.字节.getBits();} else if (c == char.class) {bits += PType.字符.getBits();} else if (c == short.class) {bits += PType.短整.getBits();} else if (c == int.class) {bits += PType.整形.getBits();System.out.println(field.getName()+ "="+ UNSAFE.getInt(obj,UNSAFE.objectFieldOffset(field)));} else if (c == float.class) {bits += PType.浮点.getBits();} else if (c == long.class) {bits += PType.长整.getBits();} else if (c == double.class) {bits += PType.双精.getBits();} else if (c == void.class) {// nothing} else if (c.isArray()) {// 是数组Object o = UNSAFE.getObject(obj,UNSAFE.objectFieldOffset(field));bits += OBJ_REF_LEN;if (o != null) {try {bits += bitsofArray(o);} catch (Exception e) {throw new RuntimeException(e);}}} else {// 普通对象Object o = UNSAFE.getObject(obj,UNSAFE.objectFieldOffset(field));bits += OBJ_REF_LEN;if (o != null) {try {bits += bitsof(o);} catch (Exception e) {throw new RuntimeException(e);}}}}}Class papa = clazz.getSuperclass();if (papa != null) {bits += getObjBits(obj, papa, true);}// 补齐,当计算父类属性时,因为是对同一个对象在进行统计,所以不要补齐。// 一个对象只做一次补齐动作。if (false == isPapa) {if (bits % ALIGN > 0) {bits += (ALIGN - bits % ALIGN);}}return bits;}/** * 计算arr数组在虚拟机中所占的内存,单位为bit *  * @param arr * @return */private static int bitsofArray(Object arr) {int bits = 0;if (arr == null) {return bits;}bits += ARRAY_BASIC_LEN;Class c = arr.getClass();if (c.isArray() == false) {throw new RuntimeException("Must be array!");}if (c == boolean[].class) {bits += PType.布尔.getBits() * ((boolean[]) arr).length;} else if (c == byte[].class) {bits += PType.字节.getBits() * ((byte[]) arr).length;} else if (c == char[].class) {bits += PType.字符.getBits() * ((char[]) arr).length;} else if (c == short[].class) {bits += PType.短整.getBits() * ((short[]) arr).length;} else if (c == int[].class) {bits += PType.整形.getBits() * ((int[]) arr).length;} else if (c == float[].class) {bits += PType.浮点.getBits() * ((float[]) arr).length;} else if (c == long[].class) {bits += PType.长整.getBits() * ((long[]) arr).length;} else if (c == double[].class) {bits += PType.双精.getBits() * ((double[]) arr).length;} else {Object[] os = (Object[]) arr;for (Object o : os) {bits += OBJ_REF_LEN + bitsof(o);}}// 补齐if (bits % ALIGN > 0) {bits += (ALIGN - bits % ALIGN);}return bits;}/** * 计算obj对象在虚拟机中所占的内存,单位为bit *  * @param obj * @return */private static int bitsof(Object obj) {if (obj == null) {return 0;}if (obj.getClass().isArray()) {return bitsofArray(obj);}return getObjBits(obj, obj.getClass(), false);}/** * 计算obj对象在虚拟机中所占的内存,单位为byte *  * @param obj * @return */public static int sizeof(Object obj) {return bitsof(obj) / 8;}private static void runGC() throws Exception {// It helps to call Runtime.gc()// using several method calls:for (int r = 0; r < 4; ++r)_runGC();}private static void _runGC() throws Exception {long usedMem1 = usedMemory(), usedMem2 = Long.MAX_VALUE;for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i) {Runtime.getRuntime().runFinalization();Runtime.getRuntime().gc();Thread.yield();usedMem2 = usedMem1;usedMem1 = usedMemory();}}private static long usedMemory() {return Runtime.getRuntime().totalMemory()- Runtime.getRuntime().freeMemory();}/** * 本方法在计算String以及原始类型的包装类的时候可能不准。 String s = "abc"; 这种方式产生的String对象会被放入常量池。 * Integer.valueOf(1)会返回缓存的对象而不是new一个。 *  * @param cls * @return * @throws Exception */private static long determinObjSize(Class cls) throws Exception {// Warm up all classes/methods we will userunGC();usedMemory();// Array to keep strong references to allocated objectsfinal int count = 100000;Object[] objects = new Object[count];long heap1 = 0;// Allocate count+1 objects, discard the first onefor (int i = -1; i < count; ++i) {Object object = null;// Instantiate your data here and assign it to object// object = new Object();// object = new Integer(i);// object = new Long(i);// object = new String();// object = new byte[128][1]object = cls.newInstance();if (i >= 0)objects[i] = object;else {object = null; // Discard the warm up objectrunGC();heap1 = usedMemory(); // Take a before heap snapshot}}runGC();long heap2 = usedMemory(); // Take an after heap snapshot:final int size = Math.round(((float) (heap2 - heap1)) / count);System.out.println("'before' heap: " + heap1 + ", 'after' heap: "+ heap2);System.out.println("heap delta: " + (heap2 - heap1) + ", {"+ objects[0].getClass() + "} size = " + size + " bytes");for (int i = 0; i < count; ++i)objects[i] = null;objects = null;return size;}/** * 校验和 *  * @param msg *            需要计算校验和的byte数组 * @param length *            校验和位数 * @return 计算出的校验和数组 */public static byte[] makeChecksum(byte[] msg, int length) {long mSum = 0;byte[] mByte = new byte[length];/** 逐Byte添加位数和 */for (byte byteMsg : msg) {long mNum = ((long) byteMsg >= 0) ? (long) byteMsg: ((long) byteMsg + 256);mSum += mNum;}/** end of for (byte byteMsg : msg) *//** 位数和转化为Byte数组 */for (int liv_Count = 0; liv_Count < length; liv_Count++) {mByte[length - liv_Count - 1] = (byte) (mSum >> (liv_Count * 8) & 0xff);}/** end of for (int liv_Count = 0; liv_Count < length; liv_Count++) */return mByte;}public static String makeChecksum(String data) {if (data == null || data.equals("")) {return "";}int total = 0;int len = data.length();int num = 0;while (num < len) {String s = data.substring(num, num + 2);System.out.println(s);total += Integer.parseInt(s, 16);num = num + 2;}/** * 用256求余最大是255,即16进制的FF */int mod = total % 256;String hex = Integer.toHexString(mod);len = hex.length();// 如果不够校验位的长度,补0,这里用的是两位校验if (len < 2) {hex = "0" + hex;}return hex;}}

0 0
原创粉丝点击