Domanda

Come faccio a a livello di codice rilevare che una situazione di stallo si è verificato in un programma Java?

Nessuna soluzione corretta

Altri suggerimenti

È possibile farlo a livello di codice utilizzando il ThreadMXBean fornito con il 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.
    }
}

Ovviamente si dovrebbe cercare di isolare qualunque discussione sta eseguendo questo controllo stallo -! In caso contrario, se quel filo deadlock non sarà in grado di eseguire il controllo

Per inciso questo è ciò che è JConsole usando sotto le coperte.

Un suggerimento utile per le indagini:

Se si può prendere l'applicazione in flagrante e sospettare una situazione di stallo si è verificato, e successivamente premere "Ctrl-Break" nella finestra della console java.exe (o "Ctrl \" su Solaris / Linux). La JVM scaricare lo stato attuale e la traccia dello stack di tutte le discussioni, per saperne di serrature morti e preciso descriverle.

Si sarà simile a questo:

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)
    ...

È possibile rilevare i fili in fase di stallo a livello di codice utilizza ThreadMXBean class.Here è il codice,

    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");
    }

qui per maggiori informazioni su come rilevare i fili in fase di stallo.

JArmus è una libreria per il rilevamento stallo e la prevenzione. Include il supporto per: Thread.join, CyclicBarrier, CountDownLatch, Phaser, e ReentrantLock.

Per usare JArmus è necessario strumento di codice. Sia attraverso una delle sue classi strumentati o automaticamente con l'instrumentar jarmusc JArmus.

java -jar jarmusc.jar yourprogram.jar checkedprogram.jar

Il yourprogram.jar ingresso è il programma che si desidera controllare. L'uscita è lo stesso programma con controlli di trovare automaticamente qualsiasi situazione di stallo.

Barriere bisogno di aiuto

Verifica bloccaporte con classi CyclicBarrier, CountDownLatch, Phaser è un po 'complicato --- per esempio, JConsole non può rilevare questi tipi di bloccaporte. JArmus ha bisogno di un piccolo aiuto da voi: è necessario specificare che le discussioni stanno influenzando la sincronizzazione, che noi chiamiamo questi registrati discussioni.

Non appena possibile, il thread deve segnare se stesso come registrato. Un buon posto per marcare le discussioni registrati è al metodo di inizio Runnable.run. JArmus.register(latch);

Esempio

Il seguente programma che deadlock sia correttamente identificato da 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();

Si potrebbe prendere in considerazione di IBM MTRAT . Prevenire è meglio che curare, dopo tutto. Il kit Multicore Software Development viene fornito con uno strumento di rilevamento deadlock.

Se non si necessita di rilevazione programmatica è possibile farlo tramite il JConsole ; sulla scheda filo c'è un pulsante "rileva stallo". In questo JDK6 rilevare serrature per entrambi i monitor intrinseche e j.u.cs Lock

Esegui il JConsole tramite il comando $JAVA_HOM/bin/jconsole

Non v'è qui il codice: http://www.java2s.com /Code/Java/Development-Class/PerformingdeadlockdetectionprogrammaticallywithintheapplicationusingthejavalangmanagementAPI.htm

La magia avviene in 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;
  }

Ciò richiede un'API del ThreadMXBean che ha un nome diverso in Java 5 e 6 (da qui il if() esterno).

L'esempio di codice consente anche di interrompere le serrature, così si può anche sbloccare la situazione.

tempus-fugit implementa anche insieme ad una classe di dumping filo di programmazione. E 'implementato utilizzando il meccanismo di MBean di cui sopra e offre un calo, out-of-the-box super-duper soluzione.

Nel caso in cui si vuole che sia fatto in fase di esecuzione è possibile utilizzare watchdog che.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top