Jusqu'à présent, je pense que l'outil le plus efficace pour analyser les problèmes de code Java reste le dump de thread Java, pour les raisons suivantes :
1. Il peut être utilisé sous n'importe quelle plate-forme de système d'exploitation.
2. Dans la plupart des cas, il peut être utilisé dans des environnements de production.
3. Par rapport aux outils fournis par le système d'exploitation, les informations fournies par java thread dump sont simples et correspondent directement au code de l'application.
4. Il a peu d’interférence avec le système analysé, il peut donc refléter des problèmes réels. De nombreux autres outils de profilage ou d'instruments interfèrent eux-mêmes avec le fonctionnement de la JVM et ne parviennent souvent pas à exposer de réels problèmes. De plus, ces outils ne peuvent pas être utilisés dans les systèmes de production.
Je pense qu'il est beaucoup plus facile d'analyser les blocages des machines virtuelles Java que les fuites de mémoire dans des circonstances normales. Parce que lorsqu'un blocage se produit, la JVM est généralement dans un état suspendu (hang) et le thread dump peut donner des informations statiques et stables. Pour trouver un blocage, il vous suffit de trouver le thread en question. Le problème des fuites de mémoire est difficile à définir. Il existe d'innombrables objets dans une JVM en cours d'exécution. Seuls ceux qui écrivent des programmes savent quels objets sont des déchets et lesquels ne le sont pas. De plus, les relations de référence des objets sont très compliquées, ce qui rend leur obtention difficile. une définition claire. Graphique de référence d’objet.
Lorsqu'un blocage de machine virtuelle Java se produit, observez depuis le système d'exploitation que l'utilisation du processeur de la machine virtuelle est nulle et disparaîtra bientôt de la sortie de top ou prstat. À ce stade, vous pouvez collecter le thread dump. Sous Unix/Linux, kill -3
Après avoir obtenu le thread dump java, il ne vous reste plus qu'à trouver le thread "en attente d'entrée du moniteur". Si un grand nombre de threads attendent d'être verrouillés à la même adresse (car pour Java, il n'y en a qu'un seul). verrouiller un objet), cela indique qu'un blocage a pu se produire. Par exemple :
"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) ................
Afin de déterminer le problème, il est souvent nécessaire de collecter à nouveau un thread dump après deux minutes si le résultat obtenu est le même et qu'il y a encore un grand nombre de threads en attente de verrouiller la même adresse. , alors ce doit être une impasse.
Comment trouver le fil de discussion qui détient actuellement le verrou est la clé pour résoudre le problème. La méthode consiste à rechercher le thread dump, à rechercher "locked <0x965d8110>" et à trouver le thread détenant le verrou.
[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)
Dans cet exemple, le thread détenant le verrou attend qu'Oracle renvoie le résultat, mais ne peut pas attendre la réponse, donc un blocage se produit.
Si le thread détenant le verrou attend toujours de verrouiller un autre objet, suivez la méthode ci-dessus jusqu'à ce que vous trouviez la source du blocage.
De plus, ces threads sont souvent observés dans les thread dumps. Ce sont des threads qui attendent une condition et abandonnent activement le verrou.
Par exemple :
"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)
Parfois il est nécessaire d'analyser ce type de fil, notamment les conditions d'attente du fil.
En fait, le thread dump Java n'est pas seulement utilisé pour analyser les blocages. D'autres comportements étranges lors de l'exécution d'applications Java peuvent être analysés avec le thread dump.
***, dans Java SE 5, l'outil jstack a été ajouté et le thread dump peut également être obtenu. Dans Java SE 6, vous pouvez également facilement trouver des blocages impliquant des moniteurs d'objets et java.util.concurrent.locks via l'outil graphique de jconsole.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!