स्मृति रिसाव को रोकने के लिए, JDBC ड्राइवर को जबरन अनरजिस्टर्ड किया गया है


325

मुझे यह संदेश तब मिल रहा है जब मैं अपना वेब एप्लिकेशन चलाता हूं। यह ठीक चलता है लेकिन मुझे यह संदेश शटडाउन के दौरान मिला।

SEVERE: एक वेब एप्लिकेशन ने JBDC ड्राइवर [oracle.jdbc.driver.OracleDriver] को पंजीकृत किया, लेकिन वेब एप्लिकेशन के बंद होने पर इसे अपंजीकृत करने में विफल रहा। स्मृति रिसाव को रोकने के लिए, JDBC ड्राइवर को जबरन अपंजीकृत किया गया है।

किसी भी मदद की सराहना की।


4
की नकली हो सकता है stackoverflow.com/questions/2604630/...
skaffman

जवाबों:


301

संस्करण 6.0.24 के बाद से, टॉमकैट एक मेमोरी लीक डिटेक्शन फीचर के साथ जहाज , जो बदले में इस तरह के चेतावनी संदेशों को जन्म दे सकता है, जब वेब में JDBC 4.0 संगत ड्राइवर है /WEB-INF/libजो ऑटो का उपयोग करता है , जो एपीआई का उपयोग करते हुए वेबैप के स्टार्टअप के दौरान खुद को पंजीकृत करता ServiceLoaderहै , लेकिन webapp के शटडाउन के दौरान खुद को ऑटो- डाइरेस्टर नहीं किया । यह संदेश पूरी तरह से अनौपचारिक है, टॉमकैट ने पहले ही स्मृति रिसाव की रोकथाम कार्रवाई को तदनुसार कर लिया है।

तुम क्या कर सकते हो?

  1. उन चेतावनियों को नजरअंदाज करें। टॉमकैट अपना काम सही कर रहा है। वास्तविक बग किसी और के कोड (प्रश्न में JDBC ड्राइवर) में है, न कि आप में। इस बात से खुश रहें कि टॉमकैट ने अपना काम ठीक से किया है और तब तक प्रतीक्षा करें जब तक कि जेडीबीसी ड्राइवर विक्रेता इसे ठीक न कर लें ताकि आप ड्राइवर को अपग्रेड कर सकें। दूसरी ओर, आप वेब में JDBC ड्राइवर को छोड़ने वाले नहीं हैं /WEB-INF/lib, लेकिन केवल सर्वर में /lib। यदि आप अभी भी इसे वेबप में रखते हैं /WEB-INF/lib, तो आपको मैन्युअल रूप से पंजीकरण करना चाहिए और ए का उपयोग करके इसे निष्क्रिय कर देना चाहिए ServletContextListener

  2. टॉम्काट 6.0.23 या पुराने को डाउनग्रेड करें ताकि आप उन चेतावनियों से परेशान न हों। लेकिन यह चुपचाप स्मृति को लीक करता रहेगा। निश्चित नहीं है कि अगर यह जानना अच्छा है। इस तरह के मेमोरी लीक टॉमकैट हॉटडिप्लमेंट्स के दौरान OutOfMemoryErrorमुद्दों के पीछे एक प्रमुख कारण हैं

  3. JDBC ड्राइवर को Tomcat के /libफ़ोल्डर में ले जाएं और ड्राइवर को प्रबंधित करने के लिए एक कनेक्शन पूलेड डेटा स्रोत है। ध्यान दें कि टॉमकैट का बिलिन डीबीसीपी ड्राइवर को ठीक से बंद नहीं करता है। बग DBCP-322 को भी देखें जो कि WONTFIX के रूप में बंद है। आप डीबीसीपी को दूसरे कनेक्शन पूल द्वारा प्रतिस्थापित करना चाहेंगे, जो तब अपना काम बेहतर तरीके से कर रहा है। उदाहरण के लिए HikariCP , BoneCP , या शायद Tomcat JDBC पूल


25
यह अच्छी सलाह है। यह एक मेमोरी लीक की चेतावनी नहीं है, यह एक चेतावनी है कि टॉमकैट ने रिसाव को रोकने के लिए कुछ जबरन कार्रवाई की
मैट बी

49
यदि विकल्प (1) जाने का रास्ता है, तो टॉमकट ने इन्हें SEVERE के रूप में लॉग इन क्यों किया है? मुझे देखने का अर्थ है "पृष्ठ व्यवस्थापक", न कि "अनदेखा"।
पीटर बेकर

7
टॉमकैट से ऐसा करने की अपेक्षा आप इसे स्वयं क्यों नहीं करते हैं। मेरी राय में, यह हमारे गंदे कोड को साफ करने के लिए टॉमकैट का काम नहीं है। नीचे मेरा जवाब देखें।
स्पार्कस्पाइडर

2
@sproketboy: हुह? क्या आप JDBC कलाकृतियों को एक वर्ग के क्षेत्र के रूप में असाइन कर रहे थे जो HTTP सत्र में बदले हुए हैं?
बालुसक

2
मुझे लगता है कि यह आमतौर पर 3 कारण है (वार के रूप में पुस्तकालय में विरोध के रूप में lib)।
लैपो

160

आपके सर्वलेट संदर्भ श्रोता संदर्भ में प्रमाणित () विधि, मैन्युअल रूप से ड्राइवरों को निष्क्रिय कर देते हैं:

// This manually deregisters JDBC driver, which prevents Tomcat 7 from complaining about memory leaks wrto this class
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
    Driver driver = drivers.nextElement();
    try {
        DriverManager.deregisterDriver(driver);
        LOG.log(Level.INFO, String.format("deregistering jdbc driver: %s", driver));
    } catch (SQLException e) {
        LOG.log(Level.SEVERE, String.format("Error deregistering driver %s", driver), e);
    }
}

3
यह काम करता हैं! javabeat.net/servletcontextlistener-example सर्वलेट संदर्भ श्रोता को लागू करने में मदद कर सकती है
वादिम ज़िन 4uk

17
यह साझा परिवेश में संभावित रूप से असुरक्षित है क्योंकि आप सभी JDBC ड्राइवरों को उपलब्ध नहीं कराना चाहते हैं जो उपलब्ध हैं। सुरक्षित दृष्टिकोण के लिए मेरा जवाब देखें ।
daiscog

85

यद्यपि टॉमकैट आपके लिए JDBC ड्राइवर को जबरन निष्क्रिय करता है, फिर भी आपके वेबऐप द्वारा बनाए गए सभी संसाधनों को संदर्भ विनाश पर साफ करने के लिए यह अच्छा अभ्यास है कि आप किसी अन्य सर्वलेट कंटेनर में जाएं जो कि मेमोरी लीक की जांच नहीं करता है जो टॉमकैट करता है।

हालांकि, कंबल चालक डेरेग्यूजन की कार्यप्रणाली खतरनाक है। DriverManager.getDrivers()हो सकता है कि विधि द्वारा लौटे कुछ ड्राइवरों को पैरेंट क्लासलोडर (यानी, सर्वलेट कंटेनर के क्लास लोडर) द्वारा लोड किया गया हो न कि वेबएप के संदर्भ के क्लासलोडर (उदाहरण के लिए, वे कंटेनर के लिबास फोल्डर में हो सकते हैं, वेबएप के नहीं और इसलिए पूरे कंटेनर में साझा किए गए )। इनका उपयोग करने से कोई भी अन्य वेबऐप प्रभावित होगा जो इनका उपयोग कर रहा होगा (या कंटेनर भी)।

इसलिए, किसी को यह जांचना चाहिए कि प्रत्येक चालक के लिए क्लासएलेडर वेबर का क्लासएलेडर है। तो, आपके संदर्भ में प्रसंगकर्ता का संदर्भडस्ट्रोइड () विधि:

public final void contextDestroyed(ServletContextEvent sce) {
    // ... First close any background tasks which may be using the DB ...
    // ... Then close any DB connection pools ...

    // Now deregister JDBC drivers in this context's ClassLoader:
    // Get the webapp's ClassLoader
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    // Loop through all drivers
    Enumeration<Driver> drivers = DriverManager.getDrivers();
    while (drivers.hasMoreElements()) {
        Driver driver = drivers.nextElement();
        if (driver.getClass().getClassLoader() == cl) {
            // This driver was registered by the webapp's ClassLoader, so deregister it:
            try {
                log.info("Deregistering JDBC driver {}", driver);
                DriverManager.deregisterDriver(driver);
            } catch (SQLException ex) {
                log.error("Error deregistering JDBC driver {}", driver, ex);
            }
        } else {
            // driver was not registered by the webapp's ClassLoader and may be in use elsewhere
            log.trace("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader", driver);
        }
    }
}

नहीं होना चाहिए if (cl.equals(driver.getClass().getClassLoader())) {?
user11153

6
@ user11153 नहीं, हम जाँच रहे हैं कि क्या यह वास्तव में एक ही ClassLoader उदाहरण है, न कि यदि यह दो अलग-अलग उदाहरण हैं जो मूल्य में समान हैं।
28'14

4
हालाँकि अन्य लोग समस्या को सही ढंग से हल करने के लिए प्रतीत होते हैं, फिर भी वे समस्या का कारण बनते हैं जब युद्ध फ़ाइल को हटा दिया जाता है और फिर बदल दिया जाता है। उस स्थिति में ड्राइवर डी-पंजीकृत होते हैं और कभी नहीं लौटते हैं - केवल एक टॉमकैट पुनरारंभ आपको उस छेद से बाहर निकाल सकता है। यह समाधान उस नरक से बचता है।
OldCurmudgeon

यहाँ ज्यादातर वही है लेकिन अतिरिक्त MySQL / MariaDB हैंडलिंग कोड के साथ github.com/spring-projects/spring-boot/issues/2612
gavenkoa

2
यदि आप H2 या PostgreSQL का उपयोग करते हैं तो ड्राइवर को पुनः लोड होने पर फिर से पंजीकृत नहीं होना पड़ता है। दोनों ड्राइवर एक आंतरिक पंजीकरण स्थिति को बनाए रखते हैं, जिसे साफ नहीं किया जाता है, तो ड्राइवर सिर्फ डीरगिस्टर किया गया है DriverManager। मैंने github.com/spring-projects/spring-boot/issues/…
Marcel 6

26

मैं देख रहा हूं कि यह मुद्दा बहुत सामने आया है। हां, टॉमकैट 7 स्वतः ही इसे निष्क्रिय कर देता है, लेकिन यह वास्तव में आपके कोड और एक अच्छा कोडिंग अभ्यास को नियंत्रित करता है? निश्चित रूप से आप जानना चाहते हैं कि आपके पास अपनी सभी वस्तुओं को बंद करने, डेटाबेस कनेक्शन पूल थ्रेड्स को बंद करने और सभी चेतावनियों से छुटकारा पाने के लिए सभी सही कोड हैं। मैं निश्चित रूप से कर दूंगा।

यह मेरा इसे करने का तरीका है।

चरण 1: एक श्रोता को पंजीकृत करें

web.xml

<listener>
    <listener-class>com.mysite.MySpecialListener</listener-class>
</listener>

चरण 2: श्रोता को लागू करें

com.mysite.MySpecialListener.java

public class MySpecialListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // On Application Startup, please…

        // Usually I'll make a singleton in here, set up my pool, etc.
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // On Application Shutdown, please…

        // 1. Go fetch that DataSource
        Context initContext = new InitialContext();
        Context envContext  = (Context)initContext.lookup("java:/comp/env");
        DataSource datasource = (DataSource)envContext.lookup("jdbc/database");

        // 2. Deregister Driver
        try {
            java.sql.Driver mySqlDriver = DriverManager.getDriver("jdbc:mysql://localhost:3306/");
            DriverManager.deregisterDriver(mySqlDriver);
        } catch (SQLException ex) {
            logger.info("Could not deregister driver:".concat(ex.getMessage()));
        } 

        // 3. For added safety, remove the reference to dataSource for GC to enjoy.
        dataSource = null;
    }

}

कृपया टिप्पणी और / या जोड़ने के लिए स्वतंत्र महसूस करें ...


4
लेकिन DataSourceएक closeविधि नहीं है
जिम

9
क्या यह लागू होना चाहिए javax.servlet.ServletContextListener, नहीं है AppContextListener का विस्तार?
अर्गगा

2
क्या विधि में उन परिचालनों के क्रम का कोई कारण है contextDestroyed? आप चरण 1 क्यों करते हैं। चरण 2 करने से पहले, कहाँ initContext, envContextऔर datasourceबिल्कुल संदर्भित नहीं हैं? मैं पूछ रहा हूं क्योंकि मुझे चरण 3 समझ में नहीं आता है
मैथ्यूस

4
@matthaeus मुझे लगता है कि चरण 1 आवश्यक नहीं है, lookupलगता है बस कुछ वस्तुओं को आपकी आवश्यकता नहीं है। चरण 3. पूरी तरह से बेकार है। यह निश्चित रूप से किसी भी सुरक्षा को नहीं जोड़ता है और ऐसा लगता है कि कुछ शुरुआती ऐसा करेंगे जो यह नहीं समझते कि जीसी कैसे काम करता है। मैं बस stackoverflow.com/a/5315467/897024 के साथ जाऊँगा और सभी ड्राइवरों को हटा दूँगा।
15

4
@kapep सभी ड्राइवरों को निकालना खतरनाक है क्योंकि कुछ कंटेनर में साझा किए जा सकते हैं। एक दृष्टिकोण के लिए मेरा जवाब देखें जो केवल आपके वेबएप के क्लासलोडर द्वारा लोड किए गए ड्राइवरों को हटा देता है।
रात 14:07

14

यह विशुद्ध रूप से mysql के ड्राइवर या टॉमकैट वेबएप-क्लास लोडर में ड्राइवर पंजीकरण / डीरेग्यूशन इश्यू है। Mysql ड्राइवर को tomcats के lib फ़ोल्डर में कॉपी करें (ताकि सीधे jvm द्वारा लोड किया जाए, tomcat द्वारा नहीं), और संदेश चला जाएगा। यह mysql jdbc ड्राइवर को केवल JVM शटडाउन पर उतारने के लिए बनाता है, और कोई भी स्मृति रिसाव के बारे में परवाह नहीं करता है।


2
यह काम नहीं करता है ... मैंने jdbc ड्राइवर को कॉपी करने की कोशिश की है जो आपने कहा है: TOMCAT_HOME / lib / postgresql-9.0-801.jdbc4.jar - Tomcat 7.0 \ lib \ postgresnl-9.0-801.jdbc4.jar जिसका कोई परिणाम नहीं है। ...
फजीर

5
@Florito - आपको इसे अपने वेब-एप्स WEB-INF / lib से हटाना होगा
Collin Peters

8

यदि आपको यह संदेश मावेन निर्मित युद्ध से दिया गया है, तो प्रदान किए गए JDBC ड्राइवर का दायरा बदल दें और इसकी एक प्रति लिबास में डाल दें। ऐशे ही:

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.18</version>
  <!-- put a copy in /usr/share/tomcat7/lib -->
  <scope>provided</scope>
</dependency>

8

प्रति ऐप तैनाती के लिए समाधान

यह एक श्रोता है जिसे मैंने समस्या को हल करने के लिए लिखा है: यह ऑटोडेटेक्ट्स है यदि ड्राइवर ने खुद को पंजीकृत किया है और तदनुसार कार्य करता है

महत्वपूर्ण: इसका उपयोग केवल तब किया जाता है जब ड्राइवर जार WEB-INF / lib में तैनात होता है , न कि Tomcat / lib में, जैसा कि कई सुझाव देते हैं, ताकि प्रत्येक एप्लिकेशन अपने स्वयं के ड्राइवर की देखभाल कर सके और अछूता Tomcat पर चला सके । यही तरीका है कि यह IMHO होना चाहिए।

बस किसी अन्य से पहले अपने web.xml में श्रोता को कॉन्फ़िगर करें और आनंद लें।

web.xml के शीर्ष के पास जोड़ें :

<listener>
    <listener-class>utils.db.OjdbcDriverRegistrationListener</listener-class>    
</listener>

बर्तनों / db / OjdbcDriverRegistrationListener.java के रूप में सहेजें :

package utils.db;

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import oracle.jdbc.OracleDriver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Registers and unregisters the Oracle JDBC driver.
 * 
 * Use only when the ojdbc jar is deployed inside the webapp (not as an
 * appserver lib)
 */
public class OjdbcDriverRegistrationListener implements ServletContextListener {

    private static final Logger LOG = LoggerFactory
            .getLogger(OjdbcDriverRegistrationListener.class);

    private Driver driver = null;

    /**
     * Registers the Oracle JDBC driver
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        this.driver = new OracleDriver(); // load and instantiate the class
        boolean skipRegistration = false;
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            if (driver instanceof OracleDriver) {
                OracleDriver alreadyRegistered = (OracleDriver) driver;
                if (alreadyRegistered.getClass() == this.driver.getClass()) {
                    // same class in the VM already registered itself
                    skipRegistration = true;
                    this.driver = alreadyRegistered;
                    break;
                }
            }
        }

        try {
            if (!skipRegistration) {
                DriverManager.registerDriver(driver);
            } else {
                LOG.debug("driver was registered automatically");
            }
            LOG.info(String.format("registered jdbc driver: %s v%d.%d", driver,
                    driver.getMajorVersion(), driver.getMinorVersion()));
        } catch (SQLException e) {
            LOG.error(
                    "Error registering oracle driver: " + 
                            "database connectivity might be unavailable!",
                    e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Deregisters JDBC driver
     * 
     * Prevents Tomcat 7 from complaining about memory leaks.
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        if (this.driver != null) {
            try {
                DriverManager.deregisterDriver(driver);
                LOG.info(String.format("deregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                LOG.warn(
                        String.format("Error deregistering driver %s", driver),
                        e);
            }
            this.driver = null;
        } else {
            LOG.warn("No driver to deregister");
        }

    }

}

टिप: सर्वलेट 3.0 के रूप में, आप कॉन्फ़िगरेशन के साथ अपनी कक्षा को एनोटेट कर सकते हैं @WebListenerऔर छोड़ सकते हैं web.xml
बेसिल बोर्के

सच है, बस यह सुनिश्चित करें कि इसे प्राथमिकता के साथ पर्याप्त रूप से उठाया गया है, ताकि किसी को पहले या बाद में ड्राइवर का उपयोग करने की आवश्यकता न हो।
एंड्रिया रट्टो

6

मैं इसे स्प्रिंग फ़ोरम पर पाए गए कुछ से जोड़ूंगा। यदि आप अपने JDBC ड्राइवर जार को टॉमकैट लिब फ़ोल्डर में ले जाते हैं, तो इसे अपने वेबएप के साथ तैनात करने के बजाय, चेतावनी गायब हो जाती है। मैं पुष्टि कर सकता हूं कि यह मेरे लिए काम कर रहा है

http://forum.springsource.org/showthread.php?87335-Failure-to-unregister-the-MySQL-JDBC-Driver&p=334883#post334883


1
मुझे लगता है कि यह एक बेहतर समाधान प्रदान करता है - बस अपने DatasourceManager को उपवर्गित करें और deregistration जोड़ने के लिए नज़दीकी विधि को ओवरराइड करें। तब स्प्रिंग इसे संभाल लेगा जब यह इसके संदर्भ को नष्ट कर देगा, और टॉमकैट आपको SEVERE लॉग नहीं देगा, और आपको अपने JDBC ड्राइवर को लिबिर डायर में स्थानांतरित करने की आवश्यकता नहीं है। यहां पुराने स्प्रिंग फ़ोरम
एडम से

6

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

/**
 * Destroys the servlet cleanly by unloading JDBC drivers.
 * 
 * @see javax.servlet.GenericServlet#destroy()
 */
public void destroy() {
    String prefix = getClass().getSimpleName() +" destroy() ";
    ServletContext ctx = getServletContext();
    try {
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while(drivers.hasMoreElements()) {
            DriverManager.deregisterDriver(drivers.nextElement());
        }
    } catch(Exception e) {
        ctx.log(prefix + "Exception caught while deregistering JDBC drivers", e);
    }
    ctx.log(prefix + "complete");
}

5
यह साझा परिवेश में संभावित रूप से असुरक्षित है क्योंकि आप सभी JDBC ड्राइवरों को उपलब्ध नहीं कराना चाहते हैं जो उपलब्ध हैं। सुरक्षित दृष्टिकोण के लिए मेरा जवाब देखें । इसके अलावा, यह वास्तव में एक सर्वलेटकोटेक्स्टलेनर में किया जाना चाहिए, प्रति-सर्वलेट के आधार पर नहीं, क्योंकि आपके JDBC ड्राइवर को आपके सभी सर्वलेट में आपके वेबप में साझा किया जाता है।
28'14

3

इस स्मृति रिसाव को रोकने के लिए, बस ड्राइवर को संदर्भ शटडाउन पर रोकें।

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mywebsite</groupId>
    <artifactId>emusicstore</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.9</source>
                    <target>1.9</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- ... -->

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.0.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <version>1.0.1.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

MyWebAppContextListener.java

package com.emusicstore.utils;

import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

public class MyWebAppContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("************** Starting up! **************");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("************** Shutting down! **************");
        System.out.println("Destroying Context...");
        System.out.println("Calling MySQL AbandonedConnectionCleanupThread checkedShutdown");
        AbandonedConnectionCleanupThread.checkedShutdown();

        ClassLoader cl = Thread.currentThread().getContextClassLoader();

        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();

            if (driver.getClass().getClassLoader() == cl) {
                try {
                    System.out.println("Deregistering JDBC driver {}");
                    DriverManager.deregisterDriver(driver);

                } catch (SQLException ex) {
                    System.out.println("Error deregistering JDBC driver {}");
                    ex.printStackTrace();
                }
            } else {
                System.out.println("Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader");
            }
        }
    }

}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <listener>
        <listener-class>com.emusicstore.utils.MyWebAppContextListener</listener-class>
    </listener>

<!-- ... -->

</web-app>

स्रोत जिसने मुझे इस बग फिक्स के लिए प्रेरित किया।


2

मुझे भी इसी तरह की समस्या हो रही थी, लेकिन इसके साथ ही मुझे एक जावा हीप स्पेस एरर भी मिल रहा था जब भी मैंने Tomcat सर्वर के साथ JSP पेजों को संशोधित / सहेजा, तो चल रहा था, इसलिए इस संदर्भ को पूरी तरह से रिचार्ज नहीं किया गया था।

मेरे संस्करण Apache Tomcat 6.0.29 और JDK 6u12 थे।

करने के लिए JDK अपग्रेड करना 6u21 के रूप में सुझाव दिया संदर्भ यूआरएल की धारा http://wiki.apache.org/tomcat/MemoryLeakProtection हल जावा ढेर अंतरिक्ष समस्या (संदर्भ अब ठीक हैं, पुन: लोड) हालांकि JDBC ड्राइवर त्रुटि अभी भी दिखाई।


0

मुझे टॉमकैट संस्करण 6.026 के साथ एक ही मुद्दा मिला।

मैंने WebAPP लाइब्रेरी के साथ-साथ TOMCAT Lib में मैसूर JDBC.jar का उपयोग किया।

TOMCAT परिवाद फ़ोल्डर से जार को हटाकर ऊपर को ठीक करने के लिए।

तो मैं जो समझता हूं, वह यह है कि TOMCAT JDBC मेमोरी लीक को ठीक से संभाल रहा है। लेकिन अगर WebSQL और Tomcat Lib में MYSQL Jdbc जार को डुप्लिकेट किया जाता है, तो Tomcat केवल Tomcat Lib फ़ोल्डर में मौजूद जार को संभालने में सक्षम होगा।


0

मुझे इस समस्या का सामना करना पड़ा है जब मैं AWS पर अपने ग्रेल्स एप्लिकेशन को तैनात कर रहा था। यह JDBC डिफॉल्ट ड्राइवर org.h2 ड्राइवर का मामला है । जैसा कि आप अपने कॉन्फ़िगरेशन फ़ोल्डर के अंदर Datasource.groovy में देख सकते हैं। जैसा कि आप नीचे देख सकते हैं:

dataSource {
    pooled = true
    jmxExport = true
    driverClassName = "org.h2.Driver"   // make this one comment
    username = "sa"
    password = ""
}

यदि आप उस डेटाबेस का उपयोग नहीं कर रहे हैं, तो उन पंक्तियों पर टिप्पणी करें जहाँ उल्लेख किया गया है। org.h2 । अन्यथा आपको उस डेटाबेस जार फ़ाइल को डाउनलोड करना होगा।

धन्यवाद ।


0

यह त्रुटि मुझे JTDS ड्राइवर 1.3.0 (SQL सर्वर) के साथ एक ग्रेल्स एप्लिकेशन में हुई। समस्या SQL सर्वर में एक गलत लॉगिन था। इस समस्या को हल करने के बाद (SQL सर्वर में) मेरे ऐप को टॉमकैट में सही ढंग से तैनात किया गया था। युक्ति: मैंने स्टैकट्रेस.लॉग में त्रुटि देखी

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.