2009-10-26 19 views
7

Znaleźliśmy błąd w starym kodzie, w którym połączenia nie są zamykane. To łatwa poprawka, ale zastanawiam się, jak staramy się udowodnić, że jest ona naprawiona. Istnieje możliwość skorzystania z puli połączeń lub nie. W przypadku korzystania z puli łatwiej byłoby dodać monitorowanie puli, ale gdy nie jest używane łączenie połączeń, w jaki sposób śledzimy te niezamknięte, osierocone połączenia? Czy to jest jak każdy inny wyciek pamięci?Jak śledzić osierocone połączenia JDBC, które nie są zamknięte?

Błąd wygląda zasadniczo jak błąd wycięcia i wklejenia. Mamy kilka klas, które zarządzają połączenia DB, więc wygląda to mniej więcej tak:

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 
} 

Nie wiem, dlaczego wcześniejsze koderzy nie tylko można ponownie użyć oryginalnego połączenia, ale to, co jest

(rozpocznij edytowanie/dołączanie)

Tak, kod połączenia jest również nasz i mogę korzystać z podanych odpowiedzi.

Jednak nie sądzę, że zadałem właściwe pytanie, chociaż poniższe odpowiedzi odpowiadają na pytanie, które zadałem. Nie jestem pewien, co należy zrobić z poprawnym stackoverflow; zadać inne pytanie, lub edytować to?

Jedno z pytań, które powinienem był zadać to: w jaki sposób te osierocone, niezamknięte połączenia przejawiają się w wydajności systemu? Ponadto, ponieważ te obiekty połączeń istnieją tylko w ramach pewnej metody, czy połączenia nie kwalifikują się do usuwania śmieci? A jeśli są gc'ed, jaki jest efekt otwartych połączeń gc'ed?

(edycja koniec)

+0

Będę uważnie obserwować ten problem, mamy bardzo podobny problem w kilku naszych projektach. – Tenner

+1

Dla przypomnienia, musiałbym mieć naprawdę dobry powód, aby NIE przenieść tego do dojrzałej implementacji puli połączeń, takiej jak DBCP lub C3PO - jeśli masz taką możliwość - może powinieneś rozważyć to? – teabot

Odpowiedz

7

Zakładając, że menedżer połączeń jest również swój własny kod, można przechowywać zainicjowane połączenia (wraz z stacktrace) na mapie w obrębie menedżer połączeń, a następnie usunąć je, gdy są zwracane . W każdym punkcie zestaw kluczy na mapie jest zbiorem niezwróconych połączeń i możesz wyszukać tę wartość na mapie, aby znaleźć kod wina, który je utworzył i nigdy go nie zwolnił. (Jeśli połączenie nie jest odpowiednim klawiszem mapy, prawdopodobnie możesz użyć unikalnego identyfikatora lub numeru połączenia lub czegoś podobnego - rzeczywista wartość nie ma znaczenia, jak jego obecność).

Następnie dodaj jakiś odpowiedni sposób, aby uzyskać dostęp do tej mapy na żądanie i jesteś dobry. W zależności od środowiska, dodanie haka zamykającego, który zrzuci zawartość mapy do pliku i/lub dodanie interfejsu JConsole w celu sprawdzenia zestawu niezamkniętych połączeń w uruchomionym kodzie, może być dobrą opcją.

Jeśli menedżer połączeń nie jest Twoim kodem, prawdopodobnie możesz osiągnąć to samo, używając aspektów.

+0

+1 dla podejścia AOP – teabot

+0

Pula połączeń, z której korzystamy, robi coś bardzo podobnego; Uważam, że zawija on połączenia, które zwraca i śledzi, kiedy są używane. Jeśli połączenie nie jest używane dłużej niż przez określony czas określony w konfiguracji, połączenie zostanie automatycznie zakończone, a ślad stosu, który został zarejestrowany podczas otwierania połączenia, zostanie wydrukowany w dzienniku. – RMorrisey

0

Można zaimplementować niestandardowy mini-framework lub użyć exisitng jako cienkiego opakowania dla operacji JDBC. Na przykład jest moduł spring-jdbc (mavenized), który obejmuje cały kod podatny na błędy od dewelopera.

Możesz sprawdzić jego usage examples i zobaczyć, że nie ma inicjalizacji/czyszczenia na kod klienta w ogóle! Używa wzoru "szablon metody", czyli po prostu piszesz niezbędne przetwarzanie danych i nie przejmuj się tworzeniem i zamykaniem połączeń/instrukcji/zestawów wyników. Tak więc nie jest możliwe wprowadzenie problemu, z którym rozmawiałeś na początku.

Powiązane problemy