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.cs Lock

Corra até a JConsole via o comando $JAVA_HOM/bin/jconsole

Há código aqui: http://www.java2s.com /Code/Java/Development-Class/PerformingdeadlockdetectionprogrammaticallywithintheapplicationusingthejavalangmanagementAPI.htm

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top