Frage

Ich begann vor kurzem eine osgi Java-Anwendung Profilierungs, die ich mit VisualVM schreibe. Eine Sache, die ich bemerkt habe ist, dass, wenn die Anwendung beginnt, Daten an einen Client zu senden (über JMS), die Anzahl der geladenen Klassen beginnt mit einer konstanten Rate zu erhöhen. Die Heap-Größe und die PermGen Größe konstant bleiben, jedoch. Die Anzahl der Klassen fällt nie, auch nachdem sie das Senden von Daten stoppt. Ist das ein Speicherleck? Ich denke, es ist, weil die geladenen Klassen müssen irgendwo gespeichert werden, aber der Haufen und Permgen nicht einmal erhöhen, nachdem ich die Anwendung für mehrere Stunden ausgeführt werden.

Für die Screenshot von meinem Profilierungsprogramm gehen hier

War es hilfreich?

Lösung

  

Sind Sie dynamisch neue Klassen on the fly zu schaffen irgendwie?

Danke für Ihre Hilfe. Ich fand heraus, was das Problem ist. In einer meiner Klassen, war ich mit jaxb eine XML-Zeichenfolge zu erstellen. Dabei dazu ueses JAXB Reflexion eine neue Klasse zu erstellen.

JAXBContext context = JAXBContext.newInstance(this.getClass());

So, obwohl die JAXBContext nicht in dem Heap sagen herum, hatten die Klassen geladen wurden.

Ich habe mein Programm wieder laufen, und ich sehe ein normales Plateau als ich erwarten würde.

Andere Tipps

Ich bin bereit zu wetten, dass Ihr Problem Generation Bytecode bezieht.

Viele Bibliotheken verwenden CGLIB, BCEL, Javasist oder Janino Bytecode für neue Klassen zur Laufzeit erzeugen und sie dann aus kontrolliert Classloader laden. Der einzige Weg, diese Klassen zu lösen ist, alle Verweise auf den Klassenlader zu lösen.

Da die Klassenlader von jeder Klasse gehalten wird, bedeutet dies auch, dass Sie nicht die Verweise auf alle Klassen als auch loslassen sollte [1]. Sie können diese mit einem anständigen Profiler fangen (I Yourkit verwenden - Suche nach mehreren Instanzen Classloader mit derselben beibehalten Größe)

Ein Haken ist, dass die JVM nicht entladen Klassen standardmäßig (der Grund ist die Abwärtskompatibilität -., Dass die Menschen übernehmen (zu Unrecht), dass statische Initialisierungen nur einmal ausgeführt werden würden Die Wahrheit ist, dass sie jedes Mal, wenn eine Klasse geladen ausgeführt werden sollen ist . To) Entladen ermöglichen, sollten Sie einige geben folgende Optionen zur Verfügung:

-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled

(getestet mit JDK 1.5)

Selbst dann ist eine übermäßige Bytecode Generation nicht eine gute Idee, so schlage ich vor, Sie in Ihrem Code suchen den Täter und Cache die generierten Klassen zu finden. Häufige Täter sind Skriptsprachen, dynamische Proxies (einschließlich der durch Anwendungsserver erzeugt sind) oder riesige Hibernate-Modell (in diesem Fall, dass Sie Ihre Permgen nur erhöhen kann).

Siehe auch:

  1. http://blogs.oracle.com/watt/resource /jvm-options-list.html
  2. http://blogs.oracle.com/jonthecollector/entry/presenting_the_permanent_generation
  3. http://forums.sun.com/thread.jspa?messageID=2833028

Sie könnten einige Hotspot-Flags finden von Nutzen zu sein, dieses Verhalten zu verstehen, wie:

  • -XX: + TraceClassLoading
  • -XX: + TraceClassUnloading

Dies ist eine gute Referenz:

http://java.sun.com/javase/technologies/hotspot /vmoptions.jsp

Wenn ich nicht falsch verstehen, wir suchen hier bei geladenen Klassen, keine Instanzen.

Wenn Ihr Code zunächst eine Klasse verweist, hat der JVM die Classloader gehen und holen die Informationen über die Klasse von einer Class-Datei oder dergleichen.

Ich bin nicht sicher, unter welchen Bedingungen es eine Klasse entladen würde. Sicherlich sollte es nie eine Klasse mit statischen Informationen entladen.

So würde ich ein Muster erwartet etwa wie bei Ihnen, wo, wie Ihre Anwendung läuft es in Bereiche und Verweise neue Klassen geht, so dass die Anzahl der geladenen Klassen gehen würde und bis.

Doch zwei Dinge scheint mir fremd:

  1. Warum ist es so linear?
  2. Warum nicht, es Plateau?

Ich würde erwarten, dass es nach oben, aber in einer wackeligen Linie zum Trend, und dann auf dem Anstieg abflachen als die JVM bereits die meisten Klassen Ihres Programm Referenzen geladen ist. Ich meine, es gibt eine endliche Anzahl von Klassen in den meisten Anwendungen verwiesen wird.

Sind Sie dynamisch neue Klassen on the fly zu schaffen irgendwie?

Ich würde vorschlagen, einen einfacheren Test-App über den gleichen Debugger laufe einen Basisfall zu erhalten. Dann könnten Sie als Ihre eigene Classloader Implementierung, die einige Debug-Informationen ausspuckt, oder vielleicht gibt es ein Werkzeug, um es Bericht.

Sie müssen herausfinden, was diese Klassen sind geladen werden.

Ja, es ist in der Regel ein Speicherleck (da wir nicht wirklich direkt mit dem Speicher umgehen, es ist eher eine Instanz der Klasse Leck). Ich habe durch diesen Prozess gegangen vor und in der Regel ist es einige Zuhörer zu einem alten Toolkit hinzugefügt, die es nicht selbst hat entfernen.

Bei älterem Code, Ein Zuhörer Beziehung bewirkt, dass das „Hörer“ Objekt um zu bleiben. Ich würde bei älteren Toolkits oder diejenigen suchen, die nicht durch viele Umdrehungen gewesen. Jede langfris vorhandene Bibliothek zu einem späteren JDK ausgeführt würde wissen, über Referenzobjekte, die die Voraussetzung für die „Entfernen Listener“ entfernt.

Auch, rufen Sie auf Ihrem Windows verfügt, wenn man sich jedes Mal neu erstellen. Ich glaube nicht, jemals sie weggehen, wenn Sie dies nicht tun (Eigentlich gibt es auch eine dispose auf eine enge Einstellung).

Keine Sorge über Schaukel oder JDK Zuhörer, sollten sie verwenden alle Referenzen, so sollten Sie in Ordnung sein.

Mit dem Eclipse-Memory Analyzer für duplizierte Klassen und Speicherlecks überprüfen. Es kann vorkommen, dass die gleiche Klasse wird mehr als einmal geladen.

Viele Grüße, Markus

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top