2016-01-11 44 views
0

我有一个使用嵌入式Jetty(版本9.3.6.v20151106)和JDK 8u65的应用程序。JVM卡住试图获取信号量

当我使用Mac或Linux操作系统这个应用程序,我没有任何困难。但是,在Windows上,Jetty无法启动并且应用程序永久挂起。

我对过程跑jstack命令并分离,其阻碍了服务器的启动该线程。

java.lang.Thread.State: WAITING (parking) 
    at sun.misc.Unsafe.park(Native Method) 
    - parking to wait for <0x1a3b2018> (a java.util.concurrent.Semaphore$NonfairSync) 
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997) 
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304) 
    at java.util.concurrent.Semaphore.acquire(Semaphore.java:312) 
    at org.eclipse.jetty.annotations.AnnotationConfiguration.scanForAnnotations(AnnotationConfiguration.java:540) 
    at org.eclipse.jetty.annotations.AnnotationConfiguration.configure(AnnotationConfiguration.java:447) 
    at org.eclipse.jetty.webapp.WebAppContext.configure(WebAppContext.java:491) 
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1336) 

我寻找另一个线程拿着锁,但没有。

如何进一步调试此问题?它是JVM错误还是Windows安全功能?任何帮助非常感谢。

+0

我尝试使用单个Java程序进行重现,但其行为方式不同。我也可以看到Windows返回的核心数是正确的。 –

回答

1

看来,Windows并没有正确报告处理器的数量。 尝试将org.eclipse.jetty.annotations.multiThreaded属性设置为false,看看是否有帮助。

+0

谢谢,试试! –

+0

我试过你的建议,但似乎没有采取。我将继续尝试(从命令行使用java -jar)。当我试图缩小范围时,我会用更多信息更新这个问题。 –

1

事实证明,我对自己的原木失明。我发现我在扫描应用程序的jar包时抛出了OOM。 有很多因素会导致这种情况发生在Windows上。首先,这是一个32位的发行版,所以在内存方面它有点反复无常。 Java的最大堆大小最终会受到这种方式的影响。

正如在#jetty IRC频道上讨论过的(由于他的杰出帮助而给予joakime的信誉和荣誉),这是由于对应用程序的WEB-INF/lib进行jar扫描。如果你有大量满是垃圾文件的罐子,这会增加启动时间并可能导致OOM。

joakime指出了两种可能性来解决这个问题:

  • 预包装并准备程序更多,并使用quickstart
  • 扫描罐子故意通过使用正则表达式来选择要扫描哪些(这page的底部)

我结束了使用了后者。我用这个正则表达式匹配JSTL罐子和弹簧罐子(我使用Spring Security的标签库JAR):

".*/jstl-[^/]*\\.jar$|.*/spring-[^/]*\\.jar$" 
+0

在弹簧组合中,不要忘记,您可以捕获所有的日志框架,并使用slf4j将它们路由到一个日志记录层。 –

0

我找了另一个线程持有了锁,但什么都没有。

信号量是比锁更一般的。这是一堆许可证,不一定与任何稀土有关。它们可以通过一个或多个线程获取和释放,并且释放并不需要在完成获取的线程上发生。

线程甚至可以创建一个信号量,消耗所有可用的许可证,然后等待自己的信号灯没有另一个线程曾触及它。

因此调试信号灯无法通过寻找其他线程“持有锁”来轻松完成。

进行调试,你必须追踪获取和释放,并看到允许被排干,然后弄清楚,他们应该被释放,但都没有。