私には奇妙な状況があります。
オブジェクトのグラフで equal() であるインスタンスを再利用できる単純な flyweight ファクトリがあります。
flyweight を使用して、または使用せずにルート オブジェクトをシリアル化してその利点を測定すると、参照ごとに新しいオブジェクトを含む 2,014,169 バイトから 1,680,865 バイトに減少します。大丈夫です。
しかし、jvisualvm のヒープ ダンプでこのオブジェクトの保持サイズを見ると、常に 6,807,832 と表示されます。
どうしてですか?確かに、あるケースで同じオブジェクトの複数のインスタンスがある場合、それらはそれぞれメモリを占有します。保持サイズは、GC から回収される量である必要があります。flyweight factory を使用してインスタンスをリサイクルしなければ、それ以上になると思います。シリアライゼーションのメリットが見られない場合は、フライウェイト ファクトリのバグだと思いますが、シリアライゼーションでのみ機能する方法がわかりません。
今、私は少し困惑しています。
flyweight ファクトリを使用して、新しいインスタンスをチェックに渡し、代わりに参照を再利用できるかどうかを確認します。
map.put(key, flyweightFactory.get(new MyClass()));
flyweight を使用しない場合は、毎回新しいオブジェクトを保存します。
map.put(key, new MyClass());
参考までに、flyweight ファクトリ クラスを次に示します。
/**
*
* Provides simple object reuse a la the flyweight pattern. Not thread safe.
*
* @author sigmund.segfeldt
*
* @param <A> type to be stored in the flyweight factory
*/
public class FlyweightFactory<A> {
private final Map<A, A> flyweights = new HashMap<>();
private int reuses = 0;
/**
*
* returns an instance of A, which is equal to the instance provided, ensuring
* that the same reference is always supplied for any such equal objects.
*
* @param instance
* @return a reference to an equal to instance, possibly instance itself
*/
public A get(A instance) {
A flyweight;
if (flyweights.containsKey(instance)) {
flyweight = flyweights.get(instance);
++reuses;
} else {
flyweights.put(instance, instance);
flyweight = instance;
}
return flyweight;
}
/**
*
* @return the size of the flyweight factory; i.e. the number of distinct objects held
*/
public int size() {
return flyweights.size();
}
/**
*
* @return number of times a flyweight has been reused, purely for statistics to see how beneficial flyweight is (without
* taking into consideration the size of reused objects, of course).
*/
public int reuses() {
return reuses;
}
@Override
public String toString() {
return "FlyweightFactory[size " + size() + ", reuses=" + reuses() + "]";
}
}