// =================================================================================================
// Copyright 2011 Twitter, Inc.
// -------------------------------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this work except in compliance with the License.
// You may obtain a copy of the License in the LICENSE file, or at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =================================================================================================
package com.rwtema.zoology.debug;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import gnu.trove.map.hash.TObjectLongHashMap;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.entity.ai.attributes.IAttribute;
import net.minecraft.item.Item;
import net.minecraft.world.World;
import org.apache.logging.log4j.Logger;
/**
* Contains utility methods for calculating the memory usage of objects. It
* only works on the HotSpot JVM, and infers the actual memory layout (32 bit
* vs. 64 bit word size, compressed object pointers vs. uncompressed) from
* best available indicators. It can reliably detect a 32 bit vs. 64 bit JVM.
* It can only make an educated guess at whether compressed OOPs are used,
* though; specifically, it knows what the JVM's default choice of OOP
* compression would be based on HotSpot version and maximum heap sizes, but if
* the choice is explicitly overridden with the -XX:{+|-}UseCompressedOops command line
* switch, it can not detect
* this fact and will report incorrect sizes, as it will presume the default JVM
* behavior.
*
* @author Attila Szegedi
*/
public class ObjectSizeCalculator {
public static final Set blackList = Sets.newIdentityHashSet();
static {
blackList.add(World.class);
blackList.add(Logger.class);
blackList.add(Block.class);
blackList.add(Class.class);
blackList.add(Item.class);
blackList.add(IAttribute.class);
}
// Fixed object header size for arrays.
private final int arrayHeaderSize;
// Fixed object header size for non-array objects.
private final int objectHeaderSize;
// Padding for the object size - if the object size is not an exact multiple
// of this, it is padded to the next multiple.
private final int objectPadding;
// Size of reference (pointer) fields.
private final int referenceSize;
// Padding for the fields of superclass before fields of subclasses are
// added.
private final int superclassFieldPadding;
private final LoadingCache, ClassSizeInfo> classSizeInfos =
CacheBuilder.newBuilder().build(new CacheLoader, ClassSizeInfo>() {
public ClassSizeInfo load(Class> clazz) {
boolean flag = blackList.contains(clazz);
for (Class aClass : blackList) {
if (flag || aClass.isAssignableFrom(clazz)) {
flag = true;
break;
}
}
if (flag) {
return new ClassSizeInfo(clazz) {
@Override
void visit(Object obj, ObjectSizeCalculator calc) {
}
@Override
public void enqueueReferencedObjects(Object obj, ObjectSizeCalculator calc) {
}
};
}
return new ClassSizeInfo(clazz);
}
});
private final Set