Ich denke, das effektivste Tool zur Analyse von Java-Codeproblemen ist immer noch Java Thread Dump, und zwar aus folgenden Gründen:
1 Es kann unter jeder Betriebssystemplattform verwendet werden.
2. In den meisten Fällen kann es in Produktionsumgebungen verwendet werden.
3. Im Vergleich zu den vom Betriebssystem bereitgestellten Tools sind die von Java Thread Dump bereitgestellten Informationen unkompliziert und entsprechen direkt dem Anwendungscode.
4. Es beeinträchtigt das analysierte System kaum und kann daher echte Probleme widerspiegeln. Viele andere Profilierungs- oder Instrumentierungstools beeinträchtigen den JVM-Betrieb erheblich und können häufig keine echten Probleme aufdecken. Darüber hinaus können solche Tools nicht in Produktionssystemen verwendet werden.
Ich denke, dass es unter normalen Umständen viel einfacher ist, Deadlocks virtueller Java-Maschinen zu analysieren als Speicherlecks. Denn wenn ein Deadlock auftritt, befindet sich die JVM normalerweise in einem angehaltenen Zustand (Hang), und der Thread-Dump kann statische und stabile Informationen liefern. Um einen Deadlock zu finden, müssen Sie nur den betreffenden Thread finden. Das Problem von Speicherlecks ist schwer zu definieren. Nur diejenigen, die Programme schreiben, wissen, welche Objekte Müll sind und welche nicht. Darüber hinaus sind die Referenzbeziehungen von Objekten sehr kompliziert, was es schwierig macht, sie zu ermitteln eine klare Definition.
Wenn ein Deadlock der Java Virtual Machine auftritt, beobachten Sie am Betriebssystem, dass die CPU-Auslastung der virtuellen Maschine Null ist und bald aus der Ausgabe von top oder prstat verschwindet. Zu diesem Zeitpunkt können Sie den Thread-Dump sammeln. Kill -3
Nachdem Sie den Java-Thread-Dump erhalten haben, müssen Sie nur noch den Thread finden, der auf den Monitoreintrag wartet. Wenn eine große Anzahl von Threads darauf wartet, an derselben Adresse gesperrt zu werden (da es für Java nur einen gibt). Sperre für ein Objekt), dies weist darauf hin, dass möglicherweise ein Deadlock aufgetreten ist. Zum Beispiel:
"service-j2ee" prio=5 tid=0x024f1c28 nid=0x125 waiting for monitor entry [62a3e000..62a3f690] [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool.internalGetResource(IASNonS haredResourcePool.java:625) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - waiting to lock <0x965d8110> (a com.sun.enterprise.resource.IASNonSharedResourcePool) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool.getResource(IASNonSharedRes ourcePool.java:520) ................
Um das Problem zu ermitteln, ist es häufig erforderlich, nach zwei Minuten erneut einen Thread-Dump zu sammeln, wenn die erhaltene Ausgabe dieselbe ist und immer noch eine große Anzahl von Threads darauf wartet, dieselbe Adresse zu sperren , dann muss es ein Deadlock sein.
Wie man den Thread findet, der derzeit die Sperre hält, ist der Schlüssel zur Lösung des Problems. Die Methode besteht darin, den Thread-Dump zu durchsuchen, nach „locked <0x965d8110>“ zu suchen und den Thread zu finden, der die Sperre hält.
[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: "Thread-20" daemon prio=5 tid=0x01394f18 nid=0x109 runnable [6716f000..6716fc28] [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at java.net.SocketInputStream.socketRead0(Native Method) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at java.net.SocketInputStream.read(SocketInputStream.java:129) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.Packet.receive(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.DataPacket.receive(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.NetInputStream.getNextPacket(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.NetInputStream.read(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.NetInputStream.read(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.NetInputStream.read(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.ttc7.MAREngine.unmarshalUB1(MAREngine.java:929) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.ttc7.MAREngine.unmarshalSB1(MAREngine.java:893) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.ttc7.Ocommoncall.receive(Ocommoncall.java:106) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.ttc7.TTC7Protocol.logoff(TTC7Protocol.java:396) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - locked <0x954f47a0> (a oracle.jdbc.ttc7.TTC7Protocol) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.driver.OracleConnection.close(OracleConnection.java:1518) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - locked <0x954f4520> (a oracle.jdbc.driver.OracleConnection) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.JdbcUrlAllocator.destroyResource(JdbcUrlAllocator.java:122) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool.destroyResource(IASNonSharedResourcePool.java:8 72) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool.resizePool(IASNonSharedResourcePool.java:1086) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - locked <0x965d8110> (a com.sun.enterprise.resource.IASNonSharedResourcePool) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool$Resizer.run(IASNonSharedResourcePool.java:1178) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at java.util.TimerThread.mainLoop(Timer.java:432) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at java.util.TimerThread.run(Timer.java:382)
In diesem Beispiel wartet der Thread, der die Sperre hält, darauf, dass Oracle das Ergebnis zurückgibt, aber er wartet nie auf die Antwort, sodass ein Deadlock auftritt.
Wenn der Thread, der die Sperre hält, immer noch darauf wartet, ein anderes Objekt zu sperren, befolgen Sie die oben beschriebene Methode, bis Sie die Ursache des Deadlocks gefunden haben.
Außerdem werden solche Threads oft in Thread-Dumps gesehen. Dabei handelt es sich um Threads, die auf eine Bedingung warten und die Sperre aktiv aufgeben.
Zum Beispiel:
"Thread-1" daemon prio=5 tid=0x014e97a8 nid=0x80 in Object.wait() [68c6f000..68c6fc28] at java.lang.Object.wait(Native Method) - waiting on <0x95b07178> (a java.util.LinkedList) at com.iplanet.ias.util.collection.BlockingQueue.remove(BlockingQueue.java:258) - locked <0x95b07178> (a java.util.LinkedList) at com.iplanet.ias.util.threadpool.FastThreadPool$ThreadPoolThread.run(FastThreadPool.java:241) at java.lang.Thread.run(Thread.java:534)
Manchmal ist es notwendig, diese Art von Thread zu analysieren, insbesondere die Bedingungen für das Warten auf Threads.
Tatsächlich wird der Java-Thread-Dump nicht nur zur Analyse von Deadlocks verwendet. Andere seltsame Verhaltensweisen beim Ausführen von Java-Anwendungen können mit dem Thread-Dump analysiert werden.
*** In Java SE 5 wurde das Jstack-Tool hinzugefügt, und es kann auch ein Thread-Dump abgerufen werden. In Java SE 6 können Sie mithilfe des grafischen Tools von jconsole auch problemlos Deadlocks finden, die Objektmonitore und java.util.concurrent.locks betreffen.
Das obige ist der detaillierte Inhalt vonWie die virtuelle Java-Maschine einen Deadlock implementiert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!