2010-06-19 6 views
5

क्या जावा ईई एप्लिकेशन में कनेक्शन रिसाव की जांच करने का कोई तरीका है?जावा ईई अनुप्रयोग में डेटाबेस कनेक्शन रिसाव की जांच कैसे करें?

एप्लिकेशन मेरी स्थानीय मशीन पर चल रहा है। यह एक MySQL डेटाबेस का उपयोग करता है और उपयोगकर्ता इस डेटाबेस में अपना विवरण दर्ज करता है।

मेरी राय में कनेक्शन रिसाव का मतलब कनेक्शन ऑब्जेक्ट को ठीक से बंद नहीं करना है। मैं अपने आवेदन में बहुत से डेटाबेस कनेक्शन बना रहा हूं। मैं जांचना चाहता हूं कि डेटाबेस कनेक्शन में कोई कनेक्शन रिसाव है या नहीं।

उत्तर

10

log4jdbc, एक जावा जेडीबीसी ड्राइवर जो एसक्यूएल और/या जेडीबीसी अन्य जेडीबीसी ड्राइवरों के लिए कॉल कर सकता है, में एक लॉगर है जो लॉग कनेक्शन कनेक्शन खोलता है और बंद करता है साथ ही सभी खुले कनेक्शन नंबरों को डंप करता है। कनेक्शन रिसाव की समस्याओं को शिकार करने के लिए यह बहुत उपयोगी है

एक अन्य उपकरण है कि आप जांच करना चाह सकते ConnLeakFinder, जावा कोड में JDBC कनेक्शन लीक इंगित करने के लिए एक सरल उपकरण है। हालांकि इसके साथ मेरा कोई अनुभव नहीं है।

+0

यह p6spy से तुलना कैसे करता है? –

+1

@ Thorbjørn मैं इसे एक आधुनिक विकल्प के रूप में मानता हूं (पी 6Spy की नवीनतम रिलीज 7+ साल पहले थी): यह एसएलएफ 4 जे का उपयोग करता है, यह मुझे कुछ फीचर्स और कॉन्फ़िगरेशन विकल्प प्रदान करता है जो यह पसंद है, यह जेडीबीसी 4 का समर्थन करता है ... मैं इसका उपयोग कर रहा हूं अब प्रतिस्थापन के रूप में। –

+0

ConnLeakFinder मेरे लिए बहुत अच्छा काम किया। लिंक के लिए धन्यवाद। –

0

FindBug का उपयोग करने का प्रयास करें। यह एक स्थिर कोड विश्लेषण उपकरण है और ग्रहण प्लगइन के साथ ही स्टैंडअलोन एप्लिकेशन के रूप में उपलब्ध है। कनेक्शन रिसाव के अलावा इसे आपके आवेदन में अन्य समस्याएं भी मिलेंगी

1

यदि आप जावा ईई ऐप सर्वर का उपयोग कर रहे हैं, तो आप कनेक्शन को जांचने के लिए इसे कॉन्फ़िगर करने में सक्षम होना चाहिए और जब वे ' वापस आओ

कनेक्शन रिसाव वास्तव में एक समस्या है। अगर आप कोड में इतने सारे स्थानों में कनेक्शन प्रबंधन बिखरे हुए थे तो मुझे चिंता होगी कि उन्हें सभी को ढूंढने में बड़ी समस्या थी। मैं एक जावा ईई कनेक्शन पूल देखने की उम्मीद करता हूं जिसका उपयोग केवल एक अच्छी तरह परिभाषित दृढ़ता परत के भीतर किया जाता था। कनेक्शन एक सेवा परत द्वारा खोला जाना चाहिए जो काम की उस इकाई के लिए लेनदेन का प्रबंधन करता है और अंत में ब्लॉक के अंत में विधि के दायरे के भीतर इसे बंद कर देता है।

यदि यह सच नहीं है, तो मुझे लगता है कि यह रिफैक्टर करने का समय है।

0

उदाहरण के लिए, एक कनेक्शन कारखाने का उपयोग करें:

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.SQLException; 

public class ConnectionFactory { 
    private static Connection connection; 

    public static synchronized Connection getConnection() throws SQLException { 
     if (connection == null || connection.isClosed()) { 
      connection = DriverManager.getConnection("url"); 
     } 
     return connection; 
    } 
} 

इस तरह से आप के पीछे पहुंच से बाहर कनेक्शन कभी नहीं छोड़ दें। यदि आपको एक से अधिक कनेक्शन (प्रदर्शन के लिए) की आवश्यकता है तो कनेक्शन पूल का उपयोग करें। अधिकांश ऐप्स सर्वर में एक जेडीबीसी कनेक्शन पूल सुविधा होती है।

0

tackle connection leaks is to do it during testing का सबसे अच्छा तरीका।

आप एक स्वचालित उपयोगिता का उपयोग कर सकते हैं ताकि प्रत्येक परीक्षण सत्यापित करता है कि कनेक्शन रिसाव है या नहीं।

@BeforeClass 
public static void initConnectionLeakUtility() { 
    if (enableConnectionLeakDetection) { 
     connectionLeakUtil = new ConnectionLeakUtil(); 
    } 
} 

@AfterClass 
public static void assertNoLeaks() { 
    if (enableConnectionLeakDetection) { 
     connectionLeakUtil.assertNoLeaks(); 
    } 
} 

ConnectionLeakUtil इस तरह दिखता है:

public class ConnectionLeakUtil { 

    private JdbcProperties jdbcProperties = JdbcProperties.INSTANCE; 

    private List idleConnectionCounters = 
     Arrays.asList(
      H2IdleConnectionCounter.INSTANCE, 
      OracleIdleConnectionCounter.INSTANCE, 
      PostgreSQLIdleConnectionCounter.INSTANCE, 
      MySQLIdleConnectionCounter.INSTANCE 
    ); 

    private IdleConnectionCounter connectionCounter; 

    private int connectionLeakCount; 

    public ConnectionLeakUtil() { 
     for (IdleConnectionCounter connectionCounter : 
      idleConnectionCounters) { 
      if (connectionCounter.appliesTo( 
       Dialect.getDialect().getClass())) { 
       this.connectionCounter = connectionCounter; 
       break; 
      } 
     } 
     if (connectionCounter != null) { 
      connectionLeakCount = countConnectionLeaks(); 
     } 
    } 

    public void assertNoLeaks() { 
     if (connectionCounter != null) { 
      int currentConnectionLeakCount = countConnectionLeaks(); 
      int diff = currentConnectionLeakCount - connectionLeakCount; 
      if (diff > 0) { 
       throw new ConnectionLeakException( 
        String.format(
         "%d connection(s) have been leaked! Previous leak count: %d, Current leak count: %d", 
         diff, 
         connectionLeakCount, 
         currentConnectionLeakCount 
        ) 
       ); 
      } 
     } 
    } 

    private int countConnectionLeaks() { 
     try (Connection connection = newConnection()) { 
      return connectionCounter.count(connection); 
     } 
     catch (SQLException e) { 
      throw new IllegalStateException(e); 
     } 
    } 

    private Connection newConnection() { 
     try { 
      return DriverManager.getConnection(
       jdbcProperties.getUrl(), 
       jdbcProperties.getUser(), 
       jdbcProperties.getPassword() 
      ); 
     } 
     catch (SQLException e) { 
      throw new IllegalStateException(e); 
     } 
    } 
} 

IdleConnectionCounter कार्यान्वयन इस blog post में पाया जा सकता है, और इस तरह MySQL संस्करण:

public class MySQLIdleConnectionCounter implements IdleConnectionCounter { 

    public static final IdleConnectionCounter INSTANCE = 
     new MySQLIdleConnectionCounter(); 

    @Override 
    public boolean appliesTo(Class<? extends Dialect> dialect) { 
     return MySQL5Dialect.class.isAssignableFrom(dialect); 
    } 

    @Override 
    public int count(Connection connection) { 
     try (Statement statement = connection.createStatement()) { 
      try (ResultSet resultSet = statement.executeQuery(
        "SHOW PROCESSLIST")) { 
       int count = 0; 
       while (resultSet.next()) { 
        String state = resultSet.getString("command"); 
        if ("sleep".equalsIgnoreCase(state)) { 
         count++; 
        } 
       } 
       return count; 
      } 
     } 
     catch (SQLException e) { 
      throw new IllegalStateException(e); 
     } 
    } 
} 

अब, जब आप चलाने के लिए अपनी परीक्षण, एक कनेक्शन लीक होने पर आपको विफलता मिल जाएगी।

संबंधित मुद्दे