好吧,这里有一个问题在这里!
1 - 如何管理短期对象?
如前所述,JVM可以完美地处理大量的短暂对象,因为它遵循Weak Generational Hypothesis。
请注意,我们正在谈论达到主内存(堆)的对象。这并非总是如此。你创建的很多对象甚至不会留下CPU寄存器。例如,考虑这个for循环
for(int i=0, i<max, i++) {
// stuff that implies i
}
我们不要考虑循环展开(JVM在您的代码上执行的优化)。如果max
等于Integer.MAX_VALUE
,则循环可能需要一些时间才能执行。但是,i
变量永远不会退出循环块。因此,JVM会将该变量放在CPU寄存器中,定期增加它,但不会将它发送回主存储器。
因此,如果仅在本地使用,创建数百万个对象并不是什么大问题。他们在被存放在伊甸园之前将会死亡,所以GC甚至不会注意到他们。
2 - 减少GC开销是否有用?
像往常一样,这取决于。
首先,您应该启用GC日志记录以清楚地了解发生了什么。您可以使用-Xloggc:gc.log -XX:+PrintGCDetails
启用它。
如果您的应用程序在GC周期中花费了大量时间,那么,是的,调整GC,否则,它可能并不值得。例如,如果你每100ms有一个需要10ms的年轻GC,那么你花10%的时间在GC上,并且每秒有10个集合(这就是huuuuuge)。在这种情况下,我不会花时间进行GC调优,因为这10个GC/s仍然会在那里。
3 - 一些经验
我上这是创造了巨大的给定类的量的应用也有类似的问题。在GC日志中,我注意到应用程序的创建速度大约为3 GB/s,这太过分了(每秒会有3 GB数据!)。
问题:由于创建的对象太多而导致频繁GC过多。
在我的情况下,我附加了一个内存分析器,并注意到一个类占我所有对象的很大一部分。我追踪了实例,发现这个类基本上是一对包裹在一个对象中的布尔值。在这种情况下,两种溶液可用:
我选择了第二个,因为它对应用程序的影响最小,很容易引入。花了我几分钟的时间才将工厂的线程安全缓存(我不需要线程安全,因为我最终只有4个不同的实例)。
分配率下降到1 GB/s,年轻GC的频率(除以3)也是如此。
希望有帮助!
Flyweight模式适合您的情况吗? http://en.wikipedia.org/wiki/Flyweight_pattern – 2013-05-07 12:38:41
你需要将它封装在一个对象中吗? – nhahtdh 2013-05-07 12:38:51
Flyweight Pattern不适用,因为对象不共享重要的公共数据。至于将数据封装在一个对象中,它太大而无法包装到一个原语中,这就是为什么我正在寻找POJO的替代品。 – 2013-05-07 12:43:51