我的程序逻辑有Spring-batch和一些带有策略模式的处理工作。 (在 JDK 8 上使用)
但是值对象太多,导致堆内存过重。
(编辑:平均一个作业有超过 50000 个对象。堆内存需要 3GB)
项目处理器
@Component
public class MyItemProcessor extends ItemProcessor<I,O> {
@Override
public O process(I item){
MyProcessor myProcessor = MyProcessorStrategyFactory.findByItem(item);
myProcessor.doJob(item);
}
}
还有我的策略部分
@Component
publc class MyProcessorA implements MyProcessor {
public void doJob(I item) {
List<VO1> vo1s = getVO1List();
List<VO2> vo2s = getVO2List();
// some logic with VO Lists...
}
}
所以我认为需要修改代码来提高性能。
我相信《Effective Java》一书中的方法一定会有效。
每当一个元素被释放时, 元素中包含的任何对象引用都应该被清空。
@Component
publc class MyProcessorA implements MyProcessor {
public void doJob(I item) {
List<VO1> vo1s = getVO1List();
List<VO2> vo2s = getVO2List();
// some logic with VO Lists...
for(VO1 vo1 : vo1s) vo1 = null;
for(VO2 vo2 : vo2s) vo2 = null; // should i nulled out this object?
vo1s = null;
vo2s = null;
}
}
或者还有什么可以提高性能的吗?
有什么好的方法可以在没有 JVisualVM 的情况下检查监控内存使用情况吗?
不,如果您接下来要清空列表本身,则单独清空列表元素是浪费时间。
如果在定义列表的方法末尾进行清空列表本身就是浪费时间。当方法退出时,所有局部变量都会超出范围。当超出范围时,它们包含的引用将被清除,达到与空赋值相同的效果。
为了解决您对内存使用情况的担忧,请单独处理每个列表。为每个列表编写一个子例程。处理第一个列表 util 后,不要实例化第二个列表 util。 砰! 您已将内存使用量减少了一半。
publc class MyProcessorA implements MyProcessor {
public void doJob(I item) {
this.doPart1() ;
this.doPart2() ;
}
private void doPart1;() {
List<VO1> vo1s = getVO1List();
// some logic with vo1s…
// vo1s going out of scoped as method exits, same effect as you assigning null.
}
private void doPart2;() {
List<VO2> vo2s = getVO2List();
// some logic with vo2s…
// vo2s going out of scoped as method exits, same effect as you assigning null.
}
}
System.gc()
的调用。但请记住,调用该 gc
方法只是对垃圾收集器的 请求,而不是 命令。
如果处理列表中的每个元素需要大量时间,那么您可以通过在处理每个元素时将其清空来提前释放内存。更好的是,看看是否可以重新设计代码,以免提前填充整个
VO1
/VO2
对象列表。