zoukankan      html  css  js  c++  java
  • java 计算sizeof,以及校验和

    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 use
    		runGC();
    		usedMemory();
    		// Array to keep strong references to allocated objects
    		final int count = 100000;
    		Object[] objects = new Object[count];
    		long heap1 = 0;
    		// Allocate count+1 objects, discard the first one
    		for (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 object
    				runGC();
    				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;
    	}
    }

  • 相关阅读:
    C++结构体成员列表初始化
    hdu-3790-最短路径问题(Dijkstra)
    hdu--1878--欧拉回路(并查集判断连通,欧拉回路模板题)
    nyoj-1278-Prototypes analyze(二叉排序树模板)
    hdu-5183-Negative and Positive (NP)(hash模板)
    nyoj-130-相同的雪花(hash)
    详细介绍C++STL:unordered_map
    NYOJ-626-intersection set(二分查找)
    hdoj-2141-Can you find it?(二分查找)
    HDU-1232-畅通工程(并查集)
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13317838.html
Copyright © 2011-2022 走看看