当JBOSS遇到System.exit()

当JBOSS在部署应用时,遇到System.exit()方法调用,会产生死锁。

我们先来看看死锁时的线程快照:

“JBoss Shutdown Hook” daemon prio=10 tid=0x0000000056fa8000 nid=0x2525 waiting for monitor entry [0x0000000047184000]

java.lang.Thread.State: BLOCKED (on object monitor)

at org.jboss.web.AbstractWebContainer.stop(AbstractWebContainer.java:494)

  • waiting to lock <0x00000000c16bc538> (a org.jboss.web.tomcat.service.JBossWeb)

 

… …

 

at org.jboss.deployment.MainDeployer.stop(MainDeployer.java:667)

at org.jboss.deployment.MainDeployer.undeploy(MainDeployer.java:638)

at org.jboss.deployment.MainDeployer.shutdown(MainDeployer.java:516)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)

at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)

at org.jboss.mx.interceptor.AbstractInterceptor.invoke(AbstractInterceptor.java:133)

at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)

at org.jboss.mx.interceptor.ModelMBeanOperationInterceptor.invoke(ModelMBeanOperationInterceptor.java:142)

at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)

at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)

at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)

at org.jboss.system.server.ServerImpl$ShutdownHook.shutdownDeployments(ServerImpl.java:1058)

at org.jboss.system.server.ServerImpl$ShutdownHook.shutdown(ServerImpl.java:1033)

at org.jboss.system.server.ServerImpl$ShutdownHook.run(ServerImpl.java:996)

 

 

“main” prio=10 tid=0x00000000550b3000 nid=0x2481 in Object.wait() [0x000000004232f000]

java.lang.Thread.State: WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

  • waiting on <0x00000000c020b250> (a org.jboss.system.server.ServerImpl$ShutdownHook)

at java.lang.Thread.join(Thread.java:1186)

  • locked <0x00000000c020b250> (a org.jboss.system.server.ServerImpl$ShutdownHook)

at java.lang.Thread.join(Thread.java:1239)

at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:79)

at java.lang.ApplicationShutdownHooks$1.run(ApplicationShutdownHooks.java:24)

at java.lang.Shutdown.runHooks(Shutdown.java:79)

at java.lang.Shutdown.sequence(Shutdown.java:123)

at java.lang.Shutdown.exit(Shutdown.java:168)

  • locked <0x00000000b05864d8> (a java.lang.Class for java.lang.Shutdown)

at java.lang.Runtime.exit(Runtime.java:90)

at java.lang.System.exit(System.java:904)

at com.taobao.matrix.galaxy.common.failover.config.ConfigManager.registerWithDiamond(ConfigManager.java:246)

at com.taobao.matrix.galaxy.common.failover.config.ConfigManager.afterPropertiesSet(ConfigManager.java:97)

 

… …

 

at org.jboss.web.AbstractWebContainer.start(AbstractWebContainer.java:466)

  • locked <0x00000000c16bc538> (a org.jboss.web.tomcat.service.JBossWeb)

 

… …

 

at org.jboss.deployment.MainDeployer.start(MainDeployer.java:1025)

at org.jboss.deployment.MainDeployer.deploy(MainDeployer.java:819)

 

… …

 

at org.jboss.Main.boot(Main.java:200)

at org.jboss.Main$1.run(Main.java:508)

at java.lang.Thread.run(Thread.java:662)

 

这里涉及到两个线程,主线程main和JBOSS的shutdown hook线程。

main线程在部署应用时,首先会获得org.jboss.web.tomcat.service.JBossWeb类的对象的锁,在获得锁后,遇到System.exit()调用,JVM会在System.exit()中调用所有注册过的shutdown hook,其中也包括JBOSS的shutdown hook,main线程会等待所有的shutdown hook执行完毕后,再恢复自身的执行,关闭虚拟机。

JBOSS的shutdown hook的行为是关闭JBOSS,在关闭之前先卸载所有部署于JBOSS的应用,卸载应用时又会尝试获取org.jboss.web.tomcat.service.JBossWeb类的对象的锁,但这个锁被main线程占有,没有释放,导致JBOSS的shutdown hook线程挂起。

此时的状态是,main线程等待shutdown hook执行完毕,shutdown hook等待main线程占有的锁,产生死锁。

 

企业级互联网架构Aliware,让您的业务能力云化:https://www.aliyun.com/aliware