tl; dr Ich glaube, Sie laufen in GC-ähnliches Verhalten, wo Fäden sein werden In Wartestatus versetzen, um die Speicherbereinigung zu ermöglichen.
Ich habe nicht die ganze Wahrheit, aber ich hoffe, einige Einblicke zu liefern.
Zuerst Sache zu realisieren ist, dass die Zahl in Klammern, [0x00007fe64df9a000]
, ist nicht die Adresse eines Monitors. Die Zahl in Klammern kann für alle Threads in einem Speicherauszug angezeigt werden, auch für Threads, die sich im Status "Running" befinden. Die Nummer ändert sich auch nicht. Beispiel aus meinem Test-Dump:
main" #1 prio=5 os_prio=0 tid=0x00007fe27c009000 nid=0x27e5c runnable [0x00007fe283bc2000]
java.lang.Thread.State: RUNNABLE
at Foo.main(Foo.java:12)
Ich bin nicht sicher, was die Zahl bedeutet, aber this page Hinweise darauf, dass es ist:
... der Zeiger auf die Java VM Innengewinde Struktur. Es ist im Allgemeinen nicht von Interesse, es sei denn, Sie debuggen eine Live-Java-VM oder Core-Datei.
Obwohl das Format der Spur erklärt dort ein bisschen anders ist, bin ich mir nicht sicher, ob ich richtig bin.
Die Art und Weise eine Müllhalde aussieht, wenn die Adresse des eigentlichen Monitor angezeigt wird:
"qtp48612937-70" #70 prio=5 os_prio=0 tid=0x00007fbb845b4800 nid=0x133c waiting for monitor entry [0x00007fbad69e8000]
java.lang.Thread.State: BLOCKED (on object monitor)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:233)
- waiting to lock <0x00000005b8d68e90> (a java.lang.Object)
Beachten Sie die waiting to lock
Linie in der Spur und dass die Adresse des Monitors aus der Zahl in Klammern unterscheidet.
Die Tatsache, dass wir die Adresse des betroffenen Monitors nicht sehen können, zeigt an, dass der Monitor nur in nativem Code existiert.
Zweitens, der betreffende Gson-Code enthält überhaupt keine Synchronisation. Der Code fügt einfach ein Element zu einer ArrayList
hinzu (vorausgesetzt, es wurde keine Bytecode-Manipulation vorgenommen und nichts wird auf niedrigem Niveau fischartig gemacht). Das heißt, es wäre nicht sinnvoll, den Thread bei diesem Aufruf auf einen Standard-Synchronisationsmonitor warten zu sehen.
Ich fand some, indications, dass Threads angezeigt werden können, wie auf einen Monitoreintrag warten, wenn es viel GC gibt.
Ich schrieb ein einfaches Testprogramm zu versuchen, es zu reproduzieren, indem nur eine Menge von Elementen zu einer Array-Liste hinzufügen:
List<String> l = new ArrayList<>();
while (true) {
for (int i = 0; i < 100_100; i++) {
l.add("" + i);
}
l = new ArrayList<>();
}
Dann nahm ich Thread-Dumps dieses Programms. Gelegentlich lief ich in die folgenden Spur:
"main" #1 prio=5 os_prio=0 tid=0x00007f35a8009000 nid=0x12448 waiting on condition [0x00007f35ac335000]
java.lang.Thread.State: RUNNABLE
at Foo.main(Foo.java:10) <--- Line of l.add()
Zwar nicht identisch mit der Spur des OP, ist es interessant, einen Thread zu haben waiting on condition
wenn keine Synchronisation beteiligt ist. Ich habe es häufiger mit einem kleineren Heap erlebt, was darauf hindeutet, dass es GC-bezogen sein könnte.
Eine andere Möglichkeit könnte sein, dass Code, der die Synchronisation enthält, JIT kompiliert wurde und das verhindert, dass Sie die tatsächliche Adresse des Monitors sehen. Ich denke jedoch, dass das weniger wahrscheinlich ist, da Sie es auf ArrayList.add
erfahren. Wenn das der Fall ist, weiß ich keine Möglichkeit, den tatsächlichen Besitzer des Monitors herauszufinden.
haben Sie versucht [Eclipse Matte] (http://www.eclipse.org/mat/)? – fhofmann
@fhofmann Ich habe keine Probleme mit Heap - wie kann es mir helfen? – bedrin
Sie haben Recht. Ich hatte vor einiger Zeit ein ähnliches Problem und habe Eclipse Mat, einen Profiler (yourkit) und einen speziellen Parser verwendet, um festzustellen, dass das Problem eine HashTable (Eigenschaften) war, die von der API-Konfiguration verwendet wurde. MAT hat mir geholfen, relevante Klassen zu finden. – fhofmann