2016-10-07 33 views
1

我有一個奇怪的情況。使用輕量級模式後visualvm保留大小相同

我有一個簡單的flyweight工廠,它允許我重用對象圖中equal()的實例。

當我序列化根對象,使用和不使用flyweight,來衡量它的好處,我從2,014,169字節和每個參考的新對象,減少到1,680,865。好的,那很好。

但是,當我在jvisualvm的堆轉儲中查看此對象的保留大小時,我總是看到6,807,832。

這怎麼可能?當然,如果在一種情況下,我有同一個對象的多個實例,它們都會佔用內存。保留的大小應該是從GC中恢復的數量。我想這可能會更多,而不使用flyweight工廠來回收實例。如果我沒有看到序列化中的好處,我認爲這是flyweight工廠中的一個錯誤,但我不明白它只能用於序列化。

現在我有點困惑。

使用輕量級的工廠,您可以通過支票通過新的情況,看是否有可以參考,而不是重複使用:

map.put(key, flyweightFactory.get(new MyClass())); 

如果不使用輕量級,每次存儲新的對象:

map.put(key, new MyClass()); 

以供參考,在這裏是輕量級工廠類:

/** 
* 
* 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() + "]"; 
    } 
} 
+0

添加visualvm的屏幕截圖。嘗試調整heapspace和不同的空間比例,以查看它是否對垃圾回收器有所幫助。 – mtk

+1

另外,也許你沒有創建一個好的測試用例來顯示你正在尋找的效果。相同數量的對象可能在兩種情況下都被創建,或者它們被某個對象持有而沒有收集垃圾 – mtk

+0

您是否在heapDump()之前在jvisualvm中執行了GC()? – olsli

回答

0

因此T他的問題是我沒有發佈輕量級工廠本身。它不是從根對象引用的,但是通過保持對flyweight對象的其他引用,它們不會計入保留的大小。

一旦我的測試用例被修復,並且除了通過根對象之外沒有對flyweights的引用,保留後的大小會隨着flyweight而增加到9.2mb,10.3mb不會通過flyweights回收相等的實例。

我被對象的保留大小愚弄了; 6.8MB只是在容器對象和引用的頭頂(假設鍵也是飛錘)。我沒有想到我的flyweights甚至沒有被計算在內。

這實際上是非常豐富的。這是一個有用的錯誤!我需要看看容器本身,看看我能否通過enummaps取代hashmaps的好處(10mb可能看起來不多,但是我的目標是低佔用空間!)

順便說一句,執行GC didn'不管有沒有flyweights,都沒有什麼不同。

感謝您的投入。