更新:
我尝试添加一些细节,因为解决这个问题对我来说非常重要。
我制作了一个批处理,它根据一些表中存在的数据生成pdf文档,并将pdf保存在表中。批处理没问题,但要处理的数据很大,所以我决定将输入数据分成8组,并独立处理8组,并且有8个并行步骤。 每一步都有自己的阅读器(步骤“X”命名为“readerX”),并且具有与其他步骤一样的处理器和写入器。
精化很顺利,但是我的客户说这个批次使用了太多内存(他看着perfmon中的“Working Set”参数)。特别是批处理以300Mb的已用内存开始,然后使用的内存达到7GB,然后减少到2GB,批处理完成,分配内存为1 / 2GB。
我在这里粘贴了工作代码,希望有人能帮助我找到问题(我想我在调整并行处理工作时犯了一些错误。)
我是春季批次的新手,所以我为“糟糕的表情”道歉。
<job id="myJob"
xmlns="http://www.springframework.org/schema/batch">
<step id="step1" next="step2">
<tasklet ref="task1" />
</step>
<step id="step2" next="step3">
<tasklet ref="task2" />
</step>
<step id="step3" next="decider">
<tasklet ref="task3" />
</step>
<decision id="decider" decider="StepExecutionDecider">
<next on="CASE X" to="split1" />
<end on="*"/>
</decision>
<split id="split1" task-executor="taskExecutor" next="endStep">
<flow>
<step id="EXEC1">
<tasklet><chunk reader="reader1" processor="processor" writer="writer" commit-interval="100"/>
<listeners>
<listener ref="Listner" />
</listeners>
</tasklet>
</step>
</flow>
<flow>
<step id="EXEC2">
<tasklet><chunk reader="reader2" processor="processor" writer="writer" commit-interval="100"/>
<listeners>
<listener ref="Listner" />
</listeners>
</tasklet>
</step>
</flow>
<flow>
<step id="EXEC3">
<tasklet><chunk reader="reader3" processor="processor" writer="writer" commit-interval="100"/>
<listeners>
<listener ref="Listner" />
</listeners>
</tasklet>
</step>
</flow>
<flow>
<step id="EXEC4">
<tasklet><chunk reader="reader4" processor="processor" writer="writer" commit-interval="100"/>
<listeners>
<listener ref="Listner" />
</listeners>
</tasklet>
</step>
</flow>
<flow>
<step id="EXEC5">
<tasklet><chunk reader="reader5" processor="processor" writer="writer" commit-interval="100"/>
<listeners>
<listener ref="Listner" />
</listeners>
</tasklet>
</step>
</flow>
<flow>
<step id="EXEC6">
<tasklet><chunk reader="reader6" processor="processor" writer="writer" commit-interval="100"/>
<listeners>
<listener ref="Listner" />
</listeners>
</tasklet>
</step>
</flow>
<flow>
<step id="EXEC7">
<tasklet><chunk reader="reader7" processor="processor" writer="writer" commit-interval="100"/>
<listeners>
<listener ref="Listner" />
</listeners>
</tasklet>
</step>
</flow>
<flow>
<step id="EXEC8">
<tasklet><chunk reader="reader8" processor="processor" writer="writer" commit-interval="100"/>
<listeners>
<listener ref="Listner" />
</listeners>
</tasklet>
</step>
</flow>
</split>
<step id="endStep" next="decider">
<tasklet ref="task4" >
<listeners>
<listener ref="Listner" />
</listeners>
</tasklet>
</step>
</job>
<bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
<bean id="reader1" class="class of the reader">
<property name="idReader" value="1"/> // Different for the 8 readers
<property name="subSet" value="10"/> // Different for the 8 readers
<property name="dao" ref="Dao" />
<property name="bean" ref="Bean" />
[...] // Other beans
</bean>
由于
答案 0 :(得分:2)
如果最终获得OOM,首先要查看堆。
使用-XX:+ HeapDumpOnOutOfMemoryError启动JVM以获取HPROF,然后您可以查看它以查看对象分配,大小等。当JVM退出OOM时,将生成此文件(可能需要一些时间,具体取决于尺寸)。
如果你能够使用更大的内存足迹(如客户端机器)运行,那么在消耗大量数据时会拍摄堆的快照,例如你提到的7GB(或任何其他被认为是高的值--4,5, 6等)。您应该能够在通过JDK等jconsole等工具运行时调用它。
使用HPROF文件,您可以使用JDK提供的工具(如jhat)或更多基于GUI的工具(如eclipse内存分析器)进行检查。这应该会给你一个很好的(并且相对容易的)方法来找出什么是什么,并提供减少足迹的起点。
答案 1 :(得分:0)
使用分析器并优化代码我成功地限制了内存消耗。谢谢大家!!!
答案 2 :(得分:0)
批处理没问题,但要处理的数据很大,所以我决定将输入数据分成8组,独立处理8组,并且有8个并行步骤。
如果您在同一台机器上并行处理,则不会减少内存占用量。所有数据同时存在于内存中。如果你想减少内存使用,你必须一个接一个地执行这些步骤。