/************************************************************************** OmegaT - Computer Assisted Translation (CAT) tool with fuzzy matching, translation memory, keyword search, glossaries, and translation leveraging into updated projects. Copyright (C) 2010 Alex Buloichik Home page: http://www.omegat.org/ Support center: http://groups.yahoo.com/group/OmegaT/ This file is part of OmegaT. OmegaT is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OmegaT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. **************************************************************************/ package org.omegat.util; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; /** * Utils for calculate used memory. * * Calculation of object size is not perfect. It doesn't support multiple links * to one object instance(object shares), memory alignments. * * @author Alex Buloichik (alex73mail@gmail.com) */ public class MemoryUtils { /** JVM architecture. */ final protected static boolean IS64 = !"32".equals(System.getProperty("sun.arch.data.model")); /** Object footprint - 16 for 64bit, 8 for 32 bit. */ final protected static int SZ_OBJFOOT = IS64 ? 16 : 8; /** Link to object - 8 for 64bit, 4 for 32bit. */ final protected static int SZ_OBJLINK = IS64 ? 8 : 4; /** * Get memory which used by jvm. * * @return memory size */ public static long getMemoryUsed() { return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); } /** * Get memory allocated by jvm. * * @return memory size */ public static long getMemoryAllocated() { return Runtime.getRuntime().totalMemory(); } /** * Get maximum memory which can be allocated by jvm. * * @return memory size */ public static long getMemoryLimit() { return Runtime.getRuntime().maxMemory(); } /** * Calculate memory usage for object. * * @param obj * object * @return memory size, or -1 if size is unknown * @throws Exception */ public static long calcObjectSize(Object obj) { if (obj == null) { return 0; } Class<?> oc = obj.getClass(); if (oc == String.class) { // make calculation for String faster String s = (String) obj; return SZ_OBJFOOT + SZ_OBJLINK + 4 + 4 + 4 + s.length() * 2; } long result; try { if (oc.isArray()) { result = getSimpleTypeSize(oc.getComponentType()) * Array.getLength(obj); if (!oc.getComponentType().isPrimitive()) { for (int i = 0; i < Array.getLength(obj); i++) { Object v = Array.get(obj, i); result += calcObjectSize(v); } } } else { result = SZ_OBJFOOT; Field[] fields = oc.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field f = fields[i]; if (Modifier.isStatic(f.getModifiers())) { continue; // static fields doesn't use memory } Class<?> fc = f.getType(); result += getSimpleTypeSize(fc); if (!fc.isPrimitive()) { boolean achanged = !f.isAccessible(); if (achanged) { f.setAccessible(true); } Object v = f.get(obj); if (achanged) { f.setAccessible(false); } result += calcObjectSize(v); } } } } catch (Exception ex) { result = -1; } return result; } /** * Calculate memory usage for simple types. * * @param oc * simple type class * @return memory size */ protected static long getSimpleTypeSize(Class<?> oc) { long result; if (oc == byte.class) { result = 1; // 1 byte for byte } else if (oc == short.class) { result = 2; // 2 bytes for short } else if (oc == int.class) { result = 4; // 4 bytes for int } else if (oc == long.class) { result = 8; // 8 bytes for long } else if (oc == char.class) { result = 2; // 2 bytes for char } else if (oc == boolean.class) { result = 1; // 1 byte for boolean } else if (oc == float.class) { result = 4; // 4 bytes for float } else if (oc == double.class) { result = 8; // 8 bytes for double } else { // Unknown class - it's not a simple type, but an object. result = SZ_OBJLINK; } return result; } }