Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 奇怪的JVM线程挂起-故障排除建议?_Java_Multithreading_Jvm_Hung - Fatal编程技术网

Java 奇怪的JVM线程挂起-故障排除建议?

Java 奇怪的JVM线程挂起-故障排除建议?,java,multithreading,jvm,hung,Java,Multithreading,Jvm,Hung,在对生产环境中的一个jvm挂起问题进行故障排除时,我们遇到了执行以下logger语句的一个线程 logger.debug("Loaded ids as " + ids + "."); 在此步骤挂起,线程状态为runnable。这是一套。还有另一个线程通过倒计时锁存器等待上述线程完成其任务。软件每15分钟进行一次线程转储,两个线程的堆栈跟踪如下所示 Stack trace for [THREAD GROUP: Job_Executor] [THREAD NAME:main-Runner Thre

在对生产环境中的一个jvm挂起问题进行故障排除时,我们遇到了执行以下logger语句的一个线程

logger.debug("Loaded ids as " + ids + ".");
在此步骤挂起,线程状态为runnable。这是一套。还有另一个线程通过倒计时锁存器等待上述线程完成其任务。软件每15分钟进行一次线程转储,两个线程的堆栈跟踪如下所示

Stack trace for [THREAD GROUP: Job_Executor] [THREAD NAME:main-Runner Thread][THREAD STATE: WAITING]
    ...sun.misc.Unsafe.park(Native Method)
    ...java.util.concurrent.locks.LockSupport.park(Unknown Source)
    ...java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
    ...java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(Unknown Source)
    ...java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(Unknown Source)
    ...java.util.concurrent.CountDownLatch.await(Unknown Source)
    ...com.runner.MainRunner.stopThread(MainRunnerRunner.java:1334)


Stack trace for [THREAD GROUP: Job_Executor] [THREAD NAME:task executor][THREAD STATE: RUNNABLE]    
    ...java.util.AbstractCollection.toString(Unknown Source)           
    ...java.lang.String.valueOf(Unknown Source)      
    ...java.lang.StringBuilder.append(Unknown Source)    
    ...com.runner.CriticalTaskExecutor.loadByIds(CriticalTaskExecutor.java:143)
这个jvm被挂起了将近24小时,最后我们不得不杀死它才能继续前进。线程转储表示有43个线程处于可运行状态,包括上述线程

仅执行collection.toString()时,上述线程24小时处于可运行状态的原因是什么


有关于如何继续的建议吗?

这取决于调用的
toString()
方法。我已经看到,当正在构造的
字符串对于堆来说太大时,
AbstractCollection.toString
就会崩溃。否则,问题可能出现在集合中对象的
toString

要确定它是哪一个,再进行一些堆栈转储(大约10次)。卡住的螺纹可能通常位于导致问题的
toString

作为快速修复,请更换

logger.debug("Loaded ids as " + ids + ".");

(假设您使用的是slf4j,否则请在框架中查找进行参数化日志记录的适当方法)

如果未启用调试,这将跳过toString

仅执行collection.toString()时,上述线程24小时处于可运行状态的原因是什么

您没有提供足够的信息来诊断问题。我只想挑战您不要假设这里存在JVM问题

如果我们查看
AbstractCollection.toString()方法的源代码,我们会看到它在集合中迭代并发出大约“[item0,item1,item2]”。调用每个
item.toString()
方法来显示该项

如果应用程序挂起在集合
toString()
中,那么我猜集合上的迭代器有问题。如果您的应用程序正在运行,您可以知道这一点——使用接近100%的CPU。可能
Set
上的
hasNext()
方法总是返回
true

如果应用程序挂起实际上位于
项.toString()
中,那么我会确保您的项只显示简单字段。小心那些如果被访问就会进行RPC调用的字段,比如延迟加载的ORM包装字段

如果您提供有关所讨论的
集合的详细信息,并显示
id.toString()
代码,我们可以提供更多帮助

现在听起来这是一组
Integer
对象。不知道为什么这会挂起你的应用程序。以下是一些其他想法:


  • 您是否以非同步方式访问此集合?是否有多个线程对集合进行了更改,导致集合损坏,从而导致其迭代器旋转?您可以尝试将其包装到一个
    Collections.synchronizedSet(…)
  • 有没有可能
    集合
    太大了,你的内存快用完了,而程序正在颠簸?但是,这不会挂起应用程序,只会使其缓慢爬行。您将开始看到内存不足异常
  • 是否有可能反复调用
    toString()
    ?不过,我想你会在日志中看到这一点

您能给我们展示一下
toString()
方法吗?是否存在延迟加载hibernate字段或其他复杂性?我将以此作为建议。感谢您指出。这如何解决
toString()
方法的问题?@Gray它没有。但他们说问题出在生产上
toString
主要面向开发人员,通常不应该在生产IMHO中调用。真的吗
toString()
在我们的环境中一直被调用以进行生产日志记录。呈现视图时,Web应用程序在容器对象上的任何地方都调用
toString()
。@artbristol很高兴看到MHO反映在YHO中。许多人认为toString不是一个对象转储程序,而是一个GUI填充程序,从而“赢得”了关于疯狂代码的讨论:(我们使用log4j,这意味着在记录语句之前,我们必须添加一个if检查,以查看日志级别是否为debug。但正如格雷所说,这似乎与问题无关。该软件在流程的进一步运行中运行良好。我们正试图了解上述罕见jvm背后的根本原因是如何挂起的。感谢您的inpu底层集合是一个HashSet。就我所知,如果代码试图对一个延迟加载的集合进行RPC调用,堆栈跟踪是否会表明这一点?我的意思是,它不会显示hibernate代码试图进行数据库调用的跟踪吗?你会这么认为,是的@Andy。我只是看不到
HashSet
挂起任何东西,所以假设问题是还有其他事情在进行。啊哈!!@AndyDufresne是否正在对此集合进行同步?是否有可能多个线程正在以非同步方式写入此集合并已将其损坏,从而导致某些内容正在旋转?您可以尝试将其包装到集合中。synchronizedSet(…)@AndyDufresne。谢谢你的想法。以下是我对你提到的上述三点的回应-1.集合没有被多个线程访问。我通过代码确认了这一点。线程转储也会表明如果是这样的话,但是没有痕迹。2.不,集合的大小不是很大。它几乎没有任何元素。另外,由于jvm被挂起超过24小时,这将确认内存没有问题。3.toString()只是在该记录器中调用的。我不认为log4j是
logger.debug("Loaded ids as {}.", ids);