我们已经将我们的企业软件从 Java 7 迁移到 Java 8,并且随之将 Spring 更新到了 4.3.4 版本。从那时起,部署失败,因为由于 StackOverflowError 无法初始化 bean 之一:
Caused By: java.lang.StackOverflowError
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
at org.springframework.scheduling.commonj.WorkManagerTaskExecutor.schedule(WorkManagerTaskExecutor.java:204)
如您所见,方法 schedule() 被递归调用,导致堆栈溢出。该应用程序部署在 Weblogic 12.1.3 版本上;这是来自 WorkManagerTaskExecutor.schedule() 的代码片段:
return this.workManager.schedule(work);
所以这应该将调度调用委托给目标 WorkManager 对象。然而,根据我们的调试分析,WorkManagerTaskExecutor内部的私有成员workManager已被初始化为WorkManagerTaskExecutor类型的实例,即this.workManager.schedule(work); 执行时,它正在调用WorkManagerTaskExecutor.schedule(),导致递归调用。
Weblogic 的目标 WorkManager 在部署描述符中设置如下: ...
<resource-ref>
<res-ref-name>wm/MyWorkManager</res-ref-name>
<res-type>commonj.work.WorkManager</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
...
<work-manager>
<name>wm/ODSCacheWorkManager</name>
<max-threads-constraint>
<name>MaxThreads</name>
<count>1</count>
</max-threads-constraint>
<ignore-stuck-threads>true</ignore-stuck-threads>
</work-manager>
...
在 Spring 应用程序上下文中:
<bean autowire="byType" id="taskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="java:comp/env/wm/MyWorkManager"/>
<property name="resourceRef" value="true"/>
</bean>
为什么WorkManagerTaskExecutor 中的 workManager 再次用 WorkManagerTaskExecutor的实例初始化,导致递归,我们严重想不通。社区能帮忙吗?