JMS DefaultMessageListenerContainer 无法在 Spring 应用程序 context.close() 上关闭
JMS DefaultMessageListenerContainer not able to shutdown on Spring application context.close()
我正在使用 spring 集成收听 Solace 动态主题,如下所示:
<int-jms:message-driven-channel-adapter
id="myJmsAdapter" channel="receiveChannel" container="jmsContainer" />
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="solaceConnectionFactory" />
<property name="destinationName" value="${my.topic}/#{main.getCar_type_value()}" />
<property name="pubSubDomain" value="true" />
<property name="sessionTransacted" value="false" />
</bean>
我能够收听主题、消费消息并处理消息。
但是在 System.exit(0)
,即使 spring 应用程序上下文在 ShutdownHook 中关闭,JMS 侦听器线程挂起并且无法正常关闭:
ctxt.registerShutdownHook();
...
trigger = new ShutdownTrigger(maxWaitForResponseMillis, ctxt);
trigger.startShutdownTimer();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
log.info("Exiting Main Thread!");
ctxt.close();
}
});
应用程序在超时时正确关闭,但是当我尝试使用 System.exit(0) 形式的其他 class 在计时器之前退出时,它没有关闭并且线程挂起。
定时器功能如下:
public void startShutdownTimer() {
timer.schedule(new TimerTask() {
@Override
public void run() {
log.info("Timer max wait has elapsed - triggering graceful
shutdown");
// perform some task here on timeout..
}
log.info("Returning with exit code: " + exitCode);
System.exit(exitCode); //this one works and it properly shutsdown
}
}, maxWaitForResponseMillis);
}
我还尝试在关闭主 class 上的上下文之前添加 Timer.cancel,如下所示,但没有成功:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
log.info("Cancelling current timer task..")
trigger.getTimer().cancel(); //it didnt work and the thread still hangs
log.info("Exiting Main Thread!");
ctxt.close();
}
});
我尝试取出 Timer 函数及其所有引用,看看是否是这个定时器线程导致了问题,但没有。即使删除了定时器任务,应用程序也会挂起。
下面是挂起时的线程栈:
"Thread-3" #26 prio=5 os_prio=0 tid=0x00007fcf48024800 nid=0x60ad in Object.wait() [0x00007fd026ef1000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at org.springframework.jms.listener.DefaultMessageListenerContainer.doShutdown(DefaultMessageListenerContainer.java:568)
- locked <0x00000000ee0c9ec0> (a java.lang.Object)
at org.springframework.jms.listener.AbstractJmsListeningContainer.shutdown(AbstractJmsListeningContainer.java:237)
请帮助找出问题和解决方案...
您正在侦听器容器线程上调用 System.exit()
"jmsContainer-1" #24 prio=5 os_prio=0 tid=0x00007fdbd8e50800 nid=0xb77 in Object.wait() [0x00007fdb9f1bc000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000f02cfb68> (a com.tdsecurities.fxts.vs.FxVsCashBalanceApp)
at java.lang.Thread.join(Thread.java:1245)
- locked <0x00000000f02cfb68> (a com.tdsecurities.fxts.vs.FxVsCashBalanceApp)
at java.lang.Thread.join(Thread.java:1319)
at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:106)
at java.lang.ApplicationShutdownHooks.run(ApplicationShutdownHooks.java:46)
at java.lang.Shutdown.runHooks(Shutdown.java:123)
at java.lang.Shutdown.sequence(Shutdown.java:167)
at java.lang.Shutdown.exit(Shutdown.java:212)
- locked <0x00000000c04335c8> (a java.lang.Class for java.lang.Shutdown)
at java.lang.Runtime.exit(Runtime.java:109)
at java.lang.System.exit(System.java:971)
这会导致应用程序上下文(Thread-3 和 Thread-5)出现死锁(关闭容器)。
您可能需要将 System.exit()
调用移交给另一个线程,但我需要知道您使用的 Spring 是哪个版本以便进一步分析。否则很难关联转储中的行号。
我正在使用 spring 集成收听 Solace 动态主题,如下所示:
<int-jms:message-driven-channel-adapter
id="myJmsAdapter" channel="receiveChannel" container="jmsContainer" />
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="solaceConnectionFactory" />
<property name="destinationName" value="${my.topic}/#{main.getCar_type_value()}" />
<property name="pubSubDomain" value="true" />
<property name="sessionTransacted" value="false" />
</bean>
我能够收听主题、消费消息并处理消息。
但是在 System.exit(0)
,即使 spring 应用程序上下文在 ShutdownHook 中关闭,JMS 侦听器线程挂起并且无法正常关闭:
ctxt.registerShutdownHook();
...
trigger = new ShutdownTrigger(maxWaitForResponseMillis, ctxt);
trigger.startShutdownTimer();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
log.info("Exiting Main Thread!");
ctxt.close();
}
});
应用程序在超时时正确关闭,但是当我尝试使用 System.exit(0) 形式的其他 class 在计时器之前退出时,它没有关闭并且线程挂起。
定时器功能如下:
public void startShutdownTimer() {
timer.schedule(new TimerTask() {
@Override
public void run() {
log.info("Timer max wait has elapsed - triggering graceful
shutdown");
// perform some task here on timeout..
}
log.info("Returning with exit code: " + exitCode);
System.exit(exitCode); //this one works and it properly shutsdown
}
}, maxWaitForResponseMillis);
}
我还尝试在关闭主 class 上的上下文之前添加 Timer.cancel,如下所示,但没有成功:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
log.info("Cancelling current timer task..")
trigger.getTimer().cancel(); //it didnt work and the thread still hangs
log.info("Exiting Main Thread!");
ctxt.close();
}
});
我尝试取出 Timer 函数及其所有引用,看看是否是这个定时器线程导致了问题,但没有。即使删除了定时器任务,应用程序也会挂起。
下面是挂起时的线程栈:
"Thread-3" #26 prio=5 os_prio=0 tid=0x00007fcf48024800 nid=0x60ad in Object.wait() [0x00007fd026ef1000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at org.springframework.jms.listener.DefaultMessageListenerContainer.doShutdown(DefaultMessageListenerContainer.java:568)
- locked <0x00000000ee0c9ec0> (a java.lang.Object)
at org.springframework.jms.listener.AbstractJmsListeningContainer.shutdown(AbstractJmsListeningContainer.java:237)
请帮助找出问题和解决方案...
您正在侦听器容器线程上调用 System.exit()
"jmsContainer-1" #24 prio=5 os_prio=0 tid=0x00007fdbd8e50800 nid=0xb77 in Object.wait() [0x00007fdb9f1bc000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000f02cfb68> (a com.tdsecurities.fxts.vs.FxVsCashBalanceApp)
at java.lang.Thread.join(Thread.java:1245)
- locked <0x00000000f02cfb68> (a com.tdsecurities.fxts.vs.FxVsCashBalanceApp)
at java.lang.Thread.join(Thread.java:1319)
at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:106)
at java.lang.ApplicationShutdownHooks.run(ApplicationShutdownHooks.java:46)
at java.lang.Shutdown.runHooks(Shutdown.java:123)
at java.lang.Shutdown.sequence(Shutdown.java:167)
at java.lang.Shutdown.exit(Shutdown.java:212)
- locked <0x00000000c04335c8> (a java.lang.Class for java.lang.Shutdown)
at java.lang.Runtime.exit(Runtime.java:109)
at java.lang.System.exit(System.java:971)
这会导致应用程序上下文(Thread-3 和 Thread-5)出现死锁(关闭容器)。
您可能需要将 System.exit()
调用移交给另一个线程,但我需要知道您使用的 Spring 是哪个版本以便进一步分析。否则很难关联转储中的行号。