java Size Of Engine
Contents
ehcache3提供了限制缓存容量的选择,如果堆上存储的容量超过了指定的大小,则会驱逐缓存中的元素,直到有空间可以容纳为止。
自己实现的sizeOfEngine应该实现ehcache3提供的引擎接口。
public interface SizeOfEngine {
/**
* Size of the objects on heap including the overhead
*
* @param key key to be sized
* @param holder value holder to be sized
* @return size of the objects on heap including the overhead
* @throws LimitExceededException if a configured limit is breached
*/
<K, V> long sizeof(K key, Store.ValueHolder<V> holder) throws LimitExceededException;
}ValueHolder包含value以及有关的元数据,比如创建时间、过期时间等。
public class DefaultSizeOfEngine implements org.ehcache.core.spi.store.heap.SizeOfEngine {
private final long maxObjectGraphSize;
private final long maxObjectSize;
private final SizeOf sizeOf;
private final long chmTreeBinOffset;
private final long onHeapKeyOffset;
public DefaultSizeOfEngine(long maxObjectGraphSize, long maxObjectSize) {
this.maxObjectGraphSize = maxObjectGraphSize;
this.maxObjectSize = maxObjectSize;
this.sizeOf = SizeOf.newInstance(new SizeOfFilterSource(true).getFilters());
this.onHeapKeyOffset = sizeOf.deepSizeOf(new CopiedOnHeapKey<>(new Object(), new IdentityCopier<>()));
this.chmTreeBinOffset = sizeOf.deepSizeOf(ConcurrentHashMap.FAKE_TREE_BIN);
}
@Override
public <K, V> long sizeof(K key, Store.ValueHolder<V> holder) throws org.ehcache.core.spi.store.heap.LimitExceededException {
try {
return sizeOf.deepSizeOf(new EhcacheVisitorListener(maxObjectGraphSize, maxObjectSize), key, holder) + this.chmTreeBinOffset + this.onHeapKeyOffset;
} catch (VisitorListenerException e) {
throw new org.ehcache.core.spi.store.heap.LimitExceededException(e.getMessage());
}
}
}我们在计算对象占用时,经常需要忽略一些对象,ehcache3提供了Filter接口来排除对象。
/**
* Filters all the sizing operation performed by a SizeOfEngine instance
*
* @author Alex Snaps
*/
public interface Filter {
/**
* Adds the class to the ignore list. Can be strict, or include subtypes
*
* @param clazz the class to ignore
* @param strict true if to be ignored strictly, or false to include sub-classes
*/
// 忽略类
void ignoreInstancesOf(final Class clazz, final boolean strict);
/**
* Adds a field to the ignore list. When that field is walked to by the SizeOfEngine, it won't navigate the graph further
*
* @param field the field to stop navigating the graph at
*/
// 忽略字段
void ignoreField(final Field field);
}/**
* Filter to filter types or fields of object graphs passed to a SizeOf engine
*
* @author Chris Dennis
* @see org.ehcache.sizeof.SizeOf
*/
public interface SizeOfFilter {
/**
* Returns the fields to walk and measure for a type
*
* @param klazz the type
* @param fields the fields already "qualified"
* @return the filtered Set
*/
Collection<Field> filterFields(Class<?> klazz, Collection<Field> fields);
/**
* Checks whether the type needs to be filtered
*
* @param klazz the type
* @return true, if to be filtered out
*/
boolean filterClass(Class<?> klazz);
}/**
* Will Cache already visited types
*/
private class CachingSizeOfVisitor implements ObjectGraphWalker.Visitor {
private final WeakIdentityConcurrentMap<Class<?>, Long> cache = new WeakIdentityConcurrentMap<>();
public long visit(final Object object) {
Class<?> klazz = object.getClass();
Long cachedSize = cache.get(klazz);
if (cachedSize == null) {
if (klazz.isArray()) {
return sizeOf(object);
} else {
long size = sizeOf(object);
cache.put(klazz, size);
return size;
}
} else {
return cachedSize;
}
}
}实现里有一个非常常用的数据结构 IdentityHashMap