Programático impasse detecção em java
-
12-09-2019 - |
Pergunta
Como posso programação detectar que um impasse ocorreu em um programa Java?
Nenhuma solução correta
Outras dicas
Você pode fazer isso por meio de programação usando o ThreadMXBean
que vem com o JDK:
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] threadIds = bean.findDeadlockedThreads(); // Returns null if no threads are deadlocked.
if (threadIds != null) {
ThreadInfo[] infos = bean.getThreadInfo(threadIds);
for (ThreadInfo info : infos) {
StackTraceElement[] stack = info.getStackTrace();
// Log or store stack trace information.
}
}
Obviamente você deve tentar isolar qualquer thread está realizando essa verificação impasse - Caso contrário, se esse segmento impasses não será capaz de executar a verificação
Aliás este é o JConsole está usando debaixo das cobertas.
Uma dica útil para a investigação:
Se você pode pegar a aplicação em flagrante e suspeitar de um impasse ocorreu, ir e pressione "Ctrl-Break" na janela do console java.exe (ou "Ctrl- \" no Solaris / Linux). A JVM vai despejar o status atual e rastreamento de pilha de todos os tópicos, descobrir fechaduras mortos e descrevê-los com precisão.
Ele será parecido com isto:
Full thread dump Java HotSpot(TM) Client VM (1.5.0_09-b03 mixed mode):
"[Test Timer] Request Queue" prio=6 tid=0x13d708d0 nid=0x1ec in Object.
wait() [0x1b00f000..0x1b00fb68]
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at library.util.AsyncQueue.run(AsyncQueue.java:138)
- locked <0x02e70000> (a test.server.scheduler.SchedulerRequestQueue)
...
Found one Java-level deadlock:
=============================
"Corba service":
waiting to lock monitor 0x13c06684 (object 0x04697d90, a java.lang.Object),
which is held by "[Server Connection] Heartbeat Timer"
"[Server Connection] Heartbeat Timer":
waiting to lock monitor 0x13c065c4 (object 0x0467e728, a test.proxy.ServerProxy), which is held by "Corba service"
Java stack information for the threads listed above:
===================================================
"Corba service":
at test.proxy.ServerProxy.stopHBWatchDog(ServerProxy:695)
- waiting to lock <0x04697d90> (a java.lang.Object)
...
Você pode detectar os fios deadlocked programaticamente usando ThreadMXBean class.Here é o código,
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long ids[] = bean.findMonitorDeadlockedThreads();
if(ids != null)
{
ThreadInfo threadInfo[] = bean.getThreadInfo(ids);
for (ThreadInfo threadInfo1 : threadInfo)
{
System.out.println(threadInfo1.getThreadId()); //Prints the ID of deadlocked thread
System.out.println(threadInfo1.getThreadName()); //Prints the name of deadlocked thread
System.out.println(threadInfo1.getLockName()); //Prints the string representation of an object for which thread has entered into deadlock.
System.out.println(threadInfo1.getLockOwnerId()); //Prints the ID of thread which currently owns the object lock
System.out.println(threadInfo1.getLockOwnerName()); //Prints name of the thread which currently owns the object lock.
}
}
else
{
System.out.println("No Deadlocked Threads");
}
Clique aqui para mais informações sobre como detectar os fios deadlocked.
JArmus é uma biblioteca para detecção de impasse e evasão. Ele inclui suporte para:
Thread.join
, CyclicBarrier
, CountDownLatch
, Phaser
, e
ReentrantLock
.
Para usar JArmus você precisa instrumento seu código. Seja através de uma de suas classes instrumentados ou automaticamente com a instrumentar jarmusc
JArmus.
java -jar jarmusc.jar yourprogram.jar checkedprogram.jar
O yourprogram.jar
de entrada é o programa que você deseja verificar.
A saída é o mesmo programa com verificações para localizar automaticamente qualquer impasse.
Barreiras precisa de alguma ajuda
Verificando impasses com aulas CyclicBarrier
, CountDownLatch
, Phaser
é um pouco complicado --- por exemplo, JConsole não consegue detectar esses tipos de impasses. JArmus precisa de um pouco de ajuda de você: você deve especificar quais tópicos estão influenciando a sincronização, nós chamamos esses registrados threads.
Assim que possível, o segmento deve marcar-se como registrado. Um bom lugar para marca registrada tópicos está no Runnable.run
método de início.
JArmus.register(latch);
Exemplo
O seguinte programa que impasses está correctamente identificado por JArmus:
final CountDownLatch latch = new CountDownLatch(2);
final CyclicBarrier barrier = new CyclicBarrier(2);
final Queue<Exception> exceptions = new ArrayDeque<>();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
JArmus.register(barrier); // do not forget to register!
JArmus.register(latch); // do not forget to register!
latch.countDown();
latch.await();
barrier.await();
} catch (Exception e) {
exceptions.add(e);
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
JArmus.register(barrier); // do not forget to register!
JArmus.register(latch); // do not forget to register!
barrier.await();
latch.countDown();
latch.await();
} catch (Exception e) {
exceptions.add(e);
}
}
});
t1.start();
t2.start();
Você pode querer considerar da IBM MTRAT . É melhor prevenir do que remediar depois de tudo. A Multicore Software Development Kit também vem com uma ferramenta de detecção de impasse.
Se você não requerem detecção programático você pode fazer isso através do JConsole ; na guia linha há um botão "Detectar impasse". Em JDK6 este detectar fechaduras para ambos os monitores intrínsecas e j.u.c
s Lock
Corra até a JConsole via o comando $JAVA_HOM/bin/jconsole
A magia acontece em ThreadMonitor.findDeadlock()
:
public boolean findDeadlock() {
long[] tids;
if (findDeadlocksMethodName.equals("findDeadlockedThreads")
&& tmbean.isSynchronizerUsageSupported()) {
tids = tmbean.findDeadlockedThreads();
if (tids == null) {
return false;
}
System.out.println("Deadlock found :-");
ThreadInfo[] infos = tmbean.getThreadInfo(tids, true, true);
for (ThreadInfo ti : infos) {
printThreadInfo(ti);
printLockInfo(ti.getLockedSynchronizers());
System.out.println();
}
} else {
tids = tmbean.findMonitorDeadlockedThreads();
if (tids == null) {
return false;
}
ThreadInfo[] infos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
for (ThreadInfo ti : infos) {
// print thread information
printThreadInfo(ti);
}
}
return true;
}
Esta chama uma API do ThreadMXBean
que tem um nome diferente em Java 5 e 6 (daí o if()
exterior).
O exemplo de código também permite interromper as fechaduras, então você pode até mesmo quebrar o impasse.
No caso de você quer que ele seja feito em tempo de execução você pode usar watchdog para isso.