2009-10-26 6 views
7

Wir haben einen Fehler im alten Code gefunden, bei dem Verbindungen nicht geschlossen werden. Es ist eine einfache Lösung, aber ich frage mich, wie wir beweisen, dass es behoben ist. Es besteht die Möglichkeit, einen Verbindungspool zu verwenden oder nicht. Für die Pooling-Nutzung wäre es einfach, die Überwachung für den Pool hinzuzufügen, aber wenn das Pooling von Verbindungen nicht verwendet wird, wie können wir diese nicht abgeschlossenen, verwaisten Verbindungen verfolgen? Ist es genau wie bei jedem anderen Speicherleck?Wie verfolge ich verwaiste JDBC-Verbindungen, die nicht geschlossen sind?

Der Fehler sieht grundsätzlich wie ein Ausschneiden und Einfügen Fehler aus. Wir haben ein paar Klassen, die die DB-Verbindung zu verwalten, so sieht es ungefähr so:

OurDBConn conn1 = ConnectionManager.getConnection(); 
try { 
    // business logic 
} catch() { 
    // 
} finally { 
    ConnectionManager.returnConnection(conn1); 
} 

/// and then later in the same method 
OurDBConn conn2 = ConnectionManager.getConnection(); 
try { 
    // business logic 
} catch() { 
    // 
} finally { 
    ConnectionManager.returnConnection(conn1); // NOTE Error: conn1 should be conn2 
} 

Ich weiß nicht, warum die früheren Programmierer einfach nicht die ursprüngliche Verbindung wieder verwenden, aber das ist, was es ist

(beginne editieren/anhängen)

Ja, der Verbindungscode gehört auch uns und so kann ich die gegebenen Antworten verwenden.

Allerdings glaube ich nicht, dass ich die richtige Frage gestellt habe, obwohl die Antworten unten die Frage beantworten, die ich gestellt habe. Ich bin mir nicht sicher, was die richtige Stackoverflow-Sache ist. eine andere Frage stellen oder diese bearbeiten?

Eine der Fragen, die ich hätte stellen sollen, ist: Wie würden sich diese verwaisten, nicht geschlossenen Verbindungen in der Systemleistung manifestieren? Da diese Verbindungsobjekte nur im Rahmen einer bestimmten Methode existieren, sind die Verbindungen nicht für die Garbage Collection geeignet? Und dann, wenn sie gc'ed sind, was ist der Effekt der offenen Verbindungen gc'ed?

(Ende edit)

+0

Ich werde diese genau beobachten, wir haben ein sehr ähnliches Problem in mehreren unserer Projekte. – Tenner

+1

Für den Rekord, ich hätte einen wirklich guten Grund, dies nicht zu einer reifen Verbindungspool-Implementierung wie DBCP oder C3PO zu verschieben - wenn Sie die Gelegenheit haben - sollten Sie vielleicht darüber nachdenken? – teabot

Antwort

7

Unter der Annahme, den Verbindungs-Manager wird auch Ihr eigener Code, können Sie die initialisierten Verbindungen speichern (zusammen mit einem Stacktrace) in einer Karte im Verbindungsmanager, und sie dann entfernen, wenn sie zurückgebracht werden . Daher ist der Schlüsselsatz der Map zu jeder Zeit die Menge der nicht zurückgegebenen Verbindungen, und Sie können diesen Wert in der Map nachschlagen, um das schuldige Bit des Codes zu finden, der sie erstellt hat, und sie nie freigegeben hat. (Wenn die Verbindung kein geeigneter Kartenschlüssel ist, können Sie wahrscheinlich eine eindeutige ID oder Verbindungsnummer oder was auch immer verwenden - der tatsächliche Wert ist nicht so wichtig wie seine Anwesenheit).

Dann fügen Sie einfach einen geeigneten Weg, um diese Karte bei Bedarf zugreifen und du bist gut. Abhängig von Ihrer Umgebung kann das Hinzufügen eines Shutdown-Hooks, mit dem der Inhalt der Map in einer Datei gespeichert wird, und/oder das Hinzufügen einer JConsole-Schnittstelle zum Nachschlagen der Gruppe nicht geschlossener Verbindungen im ausgeführten Code beide gute Optionen sein.

Wenn der Verbindungsmanager nicht Ihr Code ist, können Sie wahrscheinlich immer noch dasselbe mit Aspekten erreichen.

+0

+1 für den AOP-Ansatz – teabot

+0

Der Verbindungspool, den wir verwenden, macht etwas sehr ähnliches; Ich glaube, es wickelt die Verbindungen, die es zurückgibt, und verfolgt, wenn sie verwendet werden. Wenn eine Verbindung länger als eine bestimmte Zeit nicht verwendet wird, die wir in der Konfiguration angegeben haben, wird die Verbindung automatisch beendet und der Stack-Trace, der bei geöffneter Verbindung aufgezeichnet wurde, wird in das Protokoll gedruckt. – RMorrisey

0

Sie können ein benutzerdefiniertes Miniframework implementieren oder ein vorhandenes als Thin Wrapper für JDBC-Operationen verwenden. Zum Beispiel gibt es ein spring-jdbc Modul (mavenized), das den fehlerhaften Code des Boilerplate vom Entwickler abdeckt.

Sie können seine usage examples überprüfen und sehen, dass es keine Initialisierung/Bereinigung am Client-Code überhaupt gibt! Es verwendet 'Template-Methode' Muster, d. H. Sie schreiben nur essentielle Datenverarbeitung und kümmern sich nicht um die Erstellung und den Abschluss von Verbindungen/Anweisungen/Resultsets. Es ist also nicht möglich, das Problem, mit dem Sie zuerst gesprochen haben, vorzustellen.

Verwandte Themen