Java 使用flyweight图案后,visualvm保持尺寸不变

Java 使用flyweight图案后,visualvm保持尺寸不变,java,memory,profiling,visualvm,flyweight-pattern,Java,Memory,Profiling,Visualvm,Flyweight Pattern,我有一个奇怪的情况 我有一个简单的flyweight工厂,它允许我重用对象图中的equal()实例 当我序列化根对象(使用和不使用flyweight)来衡量它的好处时,我从2014169字节(每个引用都有一个新对象)降到1680865字节。好的,没关系 但是,当我在jvisualvm的堆转储中查看这个对象的保留大小时,我总是看到6807832 怎么可能呢?当然,如果在一个例子中我有同一个对象的多个实例,它们都会占用内存。保留大小应为从GC中回收的数量。我认为如果不使用flyweight工厂来回收

我有一个奇怪的情况

我有一个简单的flyweight工厂,它允许我重用对象图中的equal()实例

当我序列化根对象(使用和不使用flyweight)来衡量它的好处时,我从2014169字节(每个引用都有一个新对象)降到1680865字节。好的,没关系

但是,当我在jvisualvm的堆转储中查看这个对象的保留大小时,我总是看到6807832

怎么可能呢?当然,如果在一个例子中我有同一个对象的多个实例,它们都会占用内存。保留大小应为从GC中回收的数量。我认为如果不使用flyweight工厂来回收实例,情况会更糟。如果我没有看到序列化的好处,我会认为这是flyweight工厂中的一个bug,但我看不出它如何只适用于序列化

现在我有点困惑

使用flyweight factory,可以通过检查传递新实例,查看引用是否可以重新使用:

map.put(key,flyweightFactory.get(newmyclass());
如果不使用flyweight,请每次存储新对象:

map.put(key,newmyclass());
以下是flyweight factory级别,仅供参考:

/**
* 
*为flyweight图案提供简单的对象重用。不是线程安全的。
* 
*@作者sigmund.segfeldt
*
*@param type将存储在flyweight工厂中
*/
公营飞行重量工厂{
private final Map flyweights=new HashMap();
私有int重用=0;
/**
* 
*返回的实例,该实例等于提供的实例,确保
*始终为任何此类相等对象提供相同的引用。
* 
*@param实例
*@返回对等于实例的引用,可能是实例本身
*/
公共获取(实例){
飞锤;
if(flyweights.containsKey(实例)){
flyweight=flyweights.get(实例);
++再利用;
}否则{
flyweights.put(实例,实例);
flyweight=实例;
}
返回飞锤;
}
/**
* 
*@返回flyweight工厂的大小,即持有的不同对象的数量
*/
公共整数大小(){
返回flyweights.size();
}
/**
* 
*@返回飞锤被重复使用的次数,纯粹用于统计,以了解飞锤的益处(无
*当然,要考虑重用对象的大小)。
*/
公共int重用(){
回收再利用;
}
@凌驾
公共字符串toString(){
返回“FlyweightFactory[size”+size()+”,reuses=“+reuses()+”];
}
}

所以问题是我没有发布flyweight工厂本身。它不是从根对象引用的,但通过保留对flyweight对象的其他引用,它们不会计入保留的大小

一旦我的测试用例被修复,并且除了通过根对象之外没有对flyweight的引用,保留的大小随着flyweight增加到9.2mb,如果不通过flyweight循环使用相同的实例,保留的大小将增加到10.3mb

我被保留下来的物体大小所愚弄;这6.8mb只是容器对象和引用的开销(考虑到关键点也是飞锤)。我没想到我的飞锤竟然没有被计算在内

这实际上是非常有用的。这是一个有用的错误!我需要看看容器本身,看看用enummaps替换hashmaps是否能带来好处(10mb看起来不多,但我的目标是低占用空间!)

顺便说一句,执行GC没有任何区别,无论是否使用飞锤


感谢各位的支持。

所以问题是我没有发布flyweight工厂本身。它不是从根对象引用的,但通过保留对flyweight对象的其他引用,它们不会计入保留的大小

一旦我的测试用例被修复,并且除了通过根对象之外没有对flyweight的引用,保留的大小随着flyweight增加到9.2mb,如果不通过flyweight循环使用相同的实例,保留的大小将增加到10.3mb

我被保留下来的物体大小所愚弄;这6.8mb只是容器对象和引用的开销(考虑到关键点也是飞锤)。我没想到我的飞锤竟然没有被计算在内

这实际上是非常有用的。这是一个有用的错误!我需要看看容器本身,看看用enummaps替换hashmaps是否能带来好处(10mb看起来不多,但我的目标是低占用空间!)

顺便说一句,执行GC没有任何区别,无论是否使用飞锤


感谢您的支持。

添加visualvm的屏幕截图。试着调整heapspace和不同的空间比率,看看它对垃圾收集器是否有任何影响。另外,也许你没有创建一个好的测试用例来显示你想要的效果。在这两种情况下可能会创建相同数量的对象,或者它们被某个对象持有,而没有获得垃圾回收ID您在heapDump()之前在jvisualvm中执行performGC()?是的,测试用例是错误的,谢谢!将在visualvm的answeradd屏幕截图中提供更多详细信息。试着调整heapspace和不同的空间比率,看看它对垃圾收集器是否有任何影响。另外,也许你没有创建一个好的测试用例来显示你想要的效果。在这两种情况下可能会创建相同数量的对象,或者它们被某个对象持有,而没有获得垃圾回收ID您在heapDump()之前在jvisualvm中执行performGC()?是的,测试用例是错误的,谢谢!将在回答中给出更多细节