মেমরি ফাঁস রোধ করতে, জেডিবিসি ড্রাইভারকে জোর করে নিবন্ধভুক্ত করা হয়েছে


325

আমি আমার ওয়েব অ্যাপ্লিকেশনটি চালানোর সময় আমি এই বার্তাটি পাচ্ছি। এটি ঠিক আছে তবে আমি শাটডাউনের সময় এই বার্তাটি পেয়েছি।

তদন্ত: একটি ওয়েব অ্যাপ্লিকেশন জেবিডিসি ড্রাইভার [oracle.jdbc.driver.OracleDriver] নিবন্ধভুক্ত করেছে কিন্তু ওয়েব অ্যাপ্লিকেশনটি বন্ধ করা হলে এটি নিবন্ধন করতে ব্যর্থ হয়েছিল। মেমরি ফাঁস রোধ করতে, জেডিবিসি ড্রাইভারকে জোর করে নিবন্ধন করা হয়েছে।

কোন সাহায্য প্রশংসা।


4
এর সদৃশ হতে পারে stackoverflow.com/questions/2604630/...
skaffman

উত্তর:


301

সংস্করণ .0.০.২৪ থেকে, টমক্যাট একটি মেমরি ফাঁস সনাক্তকরণ বৈশিষ্ট্য সহ জাহাজগুলি যখন ওয়েবপ্যাপের একটি জেডিবিসি compatible.০ এর সাথে সামঞ্জস্যপূর্ণ ড্রাইভার উপস্থিত থাকে /WEB-INF/libযা এপিআই ব্যবহার করে ওয়েবআপের শুরুতে স্বয়ংক্রিয়ভাবে নিবন্ধিত হয় , তবে কোনটি ওয়েব অ্যাপের শাটডাউনের সময় স্বয়ংক্রিয়ভাবে নিবন্ধন করেনি। এই বার্তাটি নিখুঁতভাবে অনানুষ্ঠানিক, টমক্যাট ইতিমধ্যে সেই অনুসারে মেমরি ফাঁস প্রতিরোধের পদক্ষেপ নিয়েছে।ServiceLoader

আপনি কি করতে পারেন?

  1. সেই সতর্কতাগুলিকে উপেক্ষা করুন। টমক্যাট ঠিক তার কাজ করছে। আসল বাগটি অন্য কারও কোডে (প্রশ্নে জেডিবিসি ড্রাইভার), আপনার মধ্যে নেই। টমক্যাট তার কাজটি যথাযথভাবে করেছে এবং খুশি হোন যে জেডিবিসি ড্রাইভার বিক্রেতাকে এটি ঠিক করা না হওয়া পর্যন্ত অপেক্ষা করুন যাতে আপনি ড্রাইভারটিকে আপগ্রেড করতে পারেন। অন্যদিকে, আপনি ওয়েবডেজে কোনও জেডিবিসি ড্রাইভারকে ফেলে দেওয়ার কথা নয় /WEB-INF/lib, তবে কেবল সার্ভারের মধ্যে রয়েছে /lib। আপনি যদি এখনও এটি ওয়েব অ্যাপ্লিকেশনগুলিতে রাখেন /WEB-INF/libতবে আপনার এটি ব্যবহার করে ম্যানুয়ালি নিবন্ধভুক্ত এবং নিবন্ধন করা উচিত ServletContextListener

  2. টমক্যাট .0.০.২৩ বা তার বেশি বয়সীদের ডাউনগ্রেড করুন যাতে আপনি সেই সতর্কতাগুলির দ্বারা বিরক্ত না হন। তবে এটি নীরবে স্মৃতি ফাঁস করে দেবে। এটি সর্বোপরি জানা ভাল কিনা তা নিশ্চিত নয় Not টমক্যাট হটডেপ্লাইমেন্টস চলাকালীন OutOfMemoryErrorসমস্যাগুলির পিছনে এই ধরণের মেমরি ফুটো অন্যতম কারণ ।

  3. টমকাটের /libফোল্ডারে জেডিবিসি ড্রাইভারটি সরান এবং ড্রাইভারটি পরিচালনা করতে একটি সংযোগের সাথে পুলড ডেটাসোর্স পান। মনে রাখবেন যে টমকটের বিল্টিন ডিবিসিপি সঠিকভাবে কাছের ড্রাইভারদের নিবন্ধন করে না। এছাড়াও ডিবিসিপি -২২২ বাগটি দেখুন যা ডাব্লুউন্টফিক্স হিসাবে বন্ধ রয়েছে। আপনি বরং ডিবিসিপিকে অন্য কোনও সংযোগ পুলের দ্বারা প্রতিস্থাপন করতে চান যা তার কাজটি ডিবিসিপি আরও ভালভাবে করছে। উদাহরণস্বরূপ হিকারিসিপি , বোনসিপি বা টমকেট জেডিবিসি পুল


25
এটি ভাল পরামর্শ। এটি কোনও স্মৃতি ফাঁসের সতর্কতা নয়, এটি একটি সতর্কতা যে টমক্যাট একটি ফাঁস রোধ করতে কিছুটা জোর করে ব্যবস্থা নিয়েছিল
ম্যাট বি

49
যদি বিকল্প (1) যাওয়ার উপায় হয়, তবে টমক্যাট কেন এগুলি নিরাপদ হিসাবে লগ ইন করে? আমার কাছে অর্থ হ'ল "পৃষ্ঠা প্রশাসক", "উপেক্ষা" নয়।
পিটার বেকার

7
টমক্যাট এটি করার চেয়ে বরং এটি কেন করবেন না। আমার মতে, আমাদের অগোছালো কোড পরিষ্কার করা টমকেটের কাজ নয়। আমার উত্তর নীচে দেখুন।
স্পার্কস্পাইডার

2
@স্প্রকেটবয়: হাহ? আপনি কি এইচডিটিপি অধিবেশনগুলিতে সঞ্চিত ক্লাসের ক্ষেত্র হিসাবে জেডিবিসি শৈল্পিক কাজগুলি বরাদ্দ করেছিলেন?
বালুসসি

2
আমি অনুমান করি যে এটি সাধারণত 3 কারণ (যুদ্ধের লাইব্রেরিটির বিপরীতে রয়েছে lib)।
lapo

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- উদাহরণ সার্লেট প্রসঙ্গ শ্রোতা বাস্তবায়নে সহায়তা করতে পারে
ভাদিম জিন

17
এটি সম্ভবত ভাগ করা পরিবেশে অসুরক্ষিত কারণ আপনি যে সমস্ত জেডিবিসি ড্রাইভার উপলব্ধ রয়েছে তাদের নিবন্ধভুক্ত করতে নাও পারেন । নিরাপদ পদ্ধতির জন্য আমার উত্তরটি দেখুন ।
ডাইসকোগ

84

যদিও টমকাট জোর করে জেডিবিসি ড্রাইভারটিকে আপনার জন্য নিবন্ধন করে, তবুও আপনি টমক্যাট যে মেমরি ফাঁস প্রতিরোধের চেক করেন না যা মেমরি ফাঁস রোধকারী চেক না করে অন্য কোনও সার্লেট পাত্রে চলে গেলে প্রসঙ্গে ধ্বংসের ভিত্তিতে আপনার ওয়েব অ্যাপের দ্বারা তৈরি সমস্ত সংস্থান পরিষ্কার করা ভাল অনুশীলন।

তবে কম্বল ড্রাইভার নিবন্ধকরণের পদ্ধতিটি বিপজ্জনক। কিছু ড্রাইভার ফিরে এসেছিলDriverManager.getDrivers()পদ্ধতিতে প্যারেন্ট ক্লাসলোডার (অর্থাত্ সার্ভলেট ধারকের শ্রেণি লোডার) দ্বারা লোড হয়ে থাকতে পারে না ওয়েব অ্যাপ্লিকেশন প্রসঙ্গের ক্লাসলোডার (উদাহরণস্বরূপ, তারা কন্টেইনারের লিব ফোল্ডারে থাকতে পারে, ওয়েবঅ্যাপের নয়, এবং তাই পুরো ধারক জুড়েই ভাগ করা হয়েছে )। এগুলি নিবন্ধন করা অন্য যে কোনও ওয়েব অ্যাপ্লিকেশনগুলিকে প্রভাবিত করবে যা সেগুলি (বা এমনকি ধারক নিজেই) ব্যবহার করছে।

অতএব, একটি পরীক্ষা করা উচিত যে প্রতিটি ড্রাইভারের ক্লাসলোডারটি নিবন্ধন করার আগে ওয়েব অ্যাপের ক্লাসলোডার is সুতরাং, আপনার কনটেক্সটলিস্টারের প্রসঙ্গে ডেট্রয়েড () পদ্ধতি:

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())) {?
ব্যবহারকারী 11153

6
@ ব্যবহারকারী ১১১৫৩ না, আমরা পরীক্ষা করে দেখছি যে এটি যথাযথভাবে একই ক্লাসলোডার উদাহরণটি নয়, এটি দুটি পৃথক দৃষ্টান্ত যা মান হিসাবে সমান।
ডাইস্কোগ

4
যদিও অন্যরা মনে হয় সমস্যাটিকে সঠিকভাবে হ্যান্ডেল করেছে, যুদ্ধের ফাইলটি মুছে ফেলা এবং তারপরে প্রতিস্থাপন করা হলে তারা সমস্যার সৃষ্টি করে cause সেক্ষেত্রে ড্রাইভারগুলি নিবন্ধভুক্ত এবং কখনই ফিরে আসবে না - কেবল একটি টমক্যাট পুনঃসূচনা আপনাকে সেই গর্ত থেকে বের করে আনতে পারে। এই সমাধান সেই জাহান্নামকে এড়িয়ে চলে।
ल्डকুরিমডজিয়ন

এখানে বেশিরভাগই একই তবে অতিরিক্ত মাইএসকিউএল / মারিয়াডিবি হ্যান্ডলিং কোড github.com/spring-projects/spring-boot/issues/2612
gavenkoa

2
আপনি যদি H2 বা PostgreSQL ব্যবহার করেন তবে এই ফলাফলটি পুনরায় লোড করার পরে ড্রাইভারটি আর নিবন্ধভুক্ত হবে না। উভয় ড্রাইভারই একটি অভ্যন্তরীণ রেজিস্ট্রেশন রাষ্ট্র বজায় রাখেন যা ড্রাইভারটি কেবলমাত্র নাম থেকে নিবন্ধন করা থাকলে সাফ হয় না DriverManager। আমি github.com/spring-projects/spring-boot/issues/…
মার্সেল স্টার

26

আমি এই সমস্যাটি অনেকটা উপরে আসতে দেখছি। হ্যাঁ, টমক্যাট এটি স্বয়ংক্রিয়ভাবে নিবন্ধন করে, কিন্তু এটি কি সত্যই আপনার কোড এবং একটি ভাল কোডিং অনুশীলন নিয়ন্ত্রণ করে? অবশ্যই আপনি জানতে চান যে আপনার সমস্ত অবজেক্টগুলি বন্ধ করতে, ডাটাবেস সংযোগ পুলের থ্রেডগুলি বন্ধ করতে এবং সমস্ত সতর্কতা থেকে মুক্তি পাওয়ার জন্য আপনার কাছে সঠিক কোড রয়েছে। আমি অবশ্যই করি।

এইভাবেই আমি এটি করি।

পদক্ষেপ 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.SerletContextListener প্রয়োগ করা উচিত, অ্যাপ্লিকেশন কনটেক্সটলিস্টনার প্রসারিত না?
উদাগা

2
পদ্ধতিতে সেই ক্রিয়াকলাপগুলির আদেশের কোনও কারণ আছে কি contextDestroyed? পদক্ষেপ ২ করার আগে আপনি কেন পদক্ষেপ ১ করেন? কোথায় initContext, envContextএবং datasourceআদৌ উল্লেখ করা হয় না? আমি জিজ্ঞাসা করছি কারণ আমি পদক্ষেপ 3 বুঝতে পারি না
ম্যাথিউয়াস

4
@ ম্যাটথিউস আমি মনে করি পদক্ষেপ ১ টি প্রয়োজনীয় নয়, lookupমনে হচ্ছে কিছু জিনিস আপনার প্রয়োজন নেই objects পদক্ষেপ 3. সম্পূর্ণরূপে অকেজো। এটি অবশ্যই কোনও সুরক্ষা যুক্ত করে না এবং দেখে মনে হচ্ছে এমন কিছু এমন কিছু করবেন যারা জিসি কীভাবে কাজ করে বুঝতে পারে না। আমি কেবল স্ট্যাকওভারফ্লো.com/a/5315467/897024 নিয়ে যাব এবং সমস্ত ড্রাইভার মুছে ফেলব ।
কেপেক্স

4
@ কেপপ্প সমস্ত ড্রাইভার মুছে ফেলা বিপজ্জনক কারণ কিছু কিছু ধারক জুড়েই ভাগ করা যেতে পারে। এমন একটি পদ্ধতির জন্য আমার উত্তর দেখুন যা কেবলমাত্র আপনার ওয়েব অ্যাপ্লিকেশন এর ক্লাসলোডার দ্বারা চালিত ড্রাইভারদের সরিয়ে দেয়।
ডাইসকোগ

14

এটি মাইকিকিএলএসের ড্রাইভার বা টমক্যাটস ওয়েব অ্যাপ্লিকেশন-শ্রেণি লোডারে খালি ড্রাইভার নিবন্ধকরণ / নিবন্ধকরণের সমস্যা। টেমক্যাটস লিব ফোল্ডারে মাইএসকিএল ড্রাইভারটি অনুলিপি করুন (সুতরাং এটি সরাসরি জেভিএম দ্বারা লোড করা হয়, টমক্যাট দ্বারা নয়), এবং বার্তাটি চলে যাবে। এটি মাইএসকিএল জেডিবিসি ড্রাইভারকে কেবল জেভিএম শাটডাউন-এ আনলোড করতে সক্ষম করে, এবং নুনি তখন মেমরি ফাঁস সম্পর্কে চিন্তা করে না।


2
এটি কাজ করে না ... আমি jdbc ড্রাইভারটি অনুলিপি করার চেষ্টা করেছি আপনি বলেছেন: TOMCAT_HOME / lib / postgresql-9.0-801.jdbc4.jar - টমক্যাট 7.0 \ lib \ postgresql-9.0-801.jdbc4.jar কোনও ফলাফল ছাড়াই ...
FAjir

5
@ ফ্লোরিটো - আপনাকে এটি আপনার ওয়েব-অ্যাপস থেকে ওয়েবে-আইএনএফ / লাইব থেকেও সরিয়ে ফেলতে হবে
কলিন পিটারস 16

8

যদি আপনি এই বার্তাটি কোনও ম্যাভেন নির্মিত যুদ্ধের থেকে পেয়ে থাকেন তবে জেডিবিসি ড্রাইভারের সুযোগ সরবরাহের সুযোগ পরিবর্তন করুন এবং এটির একটি অনুলিপি লাইব ডিরেক্টরিতে রেখে দিন। এটার মত:

<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

প্রতি অ্যাপ্লিকেশন মোতায়েনের জন্য সমাধান

সমস্যাটি সমাধান করার জন্য আমি এটি লিখেছি এমন একটি শ্রোতা: ড্রাইভার নিজেই নিবন্ধিত হয়েছে এবং সে অনুযায়ী কাজ করে তবে এটি স্বয়ংক্রিয়ভাবে আবিষ্কার করে it

গুরুত্বপূর্ণ: এটি ব্যবহার করা বোঝায় কেবলমাত্র চালক জার যখন -আইএনএফ / লিবিতে স্থাপন করা হয় তবে টমকেট / লিবিবে নয়, যেমনটি অনেকেই পরামর্শ দেন, যাতে প্রতিটি অ্যাপ্লিকেশন তার নিজের চালকের যত্ন নিতে পারে এবং কোনও টমকাট চালাতে পারে না । এটি আইএমএইচও হওয়া উচিত।

অন্য শ্রেনীর আগে কেবল আপনার ওয়েব.এক্সএমএলে শ্রোতাদের কনফিগার করুন এবং উপভোগ করুন।

ওয়েব.এক্সএমএল শীর্ষের কাছাকাছি যুক্ত করুন :

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

ইউজ / ডিবি / ওজেডবিসিড্রাইভার রেজিস্ট্রেশনলিস্টার.জভা হিসাবে সংরক্ষণ করুন :

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
বাসিল বাউরেক

সত্য, এটি নিশ্চিত হয়ে নিন যে এটি যথেষ্ট অগ্রাধিকারের সাথে উঠেছে, যাতে কারও আগে বা পরে ড্রাইভার ব্যবহার করার প্রয়োজন হয় না।
আন্দ্রে রাত্তো 24'16

6

আমি স্প্রিং ফোরামগুলিতে পাওয়া কিছুতে এটি যুক্ত করব। আপনি যদি আপনার জেডিবিসি ড্রাইভার জারটি আপনার ওয়েব অ্যাপের সাহায্যে স্থাপনের পরিবর্তে টমক্যাট লাইব ফোল্ডারে নিয়ে যান তবে সতর্কতাটি অদৃশ্য হয়ে যাবে বলে মনে হচ্ছে। আমি নিশ্চিত করতে পারি যে এটি আমার জন্য কাজ করেছে

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


1
আমি মনে করি এটি আরও ভাল সমাধান দেয় - কেবল আপনার ডেটাসোর্স ম্যানেজারটি সাবক্লাস করুন এবং নিবন্ধকরণ যুক্ত করার জন্য নিকটতম পদ্ধতিটি ওভাররাইড করুন। তারপরে স্প্রিং এটি পরিচালনা করবে যখন এটি তার প্রসঙ্গটি ধ্বংস করবে এবং টমক্যাট আপনাকে সংরক্ষণের লগ দেবে না এবং আপনাকে আপনার জেডিবিসি ড্রাইভারটিকে লিবিব ডায়ারে সরিয়ে নিতে হবে না। পুরানো বসন্ত ফোরামের
আদম

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
এটি সম্ভবত ভাগ করা পরিবেশে অসুরক্ষিত কারণ আপনি যে সমস্ত জেডিবিসি ড্রাইভার উপলব্ধ রয়েছে তাদের নিবন্ধভুক্ত করতে নাও পারেন । নিরাপদ পদ্ধতির জন্য আমার উত্তরটি দেখুন । এছাড়াও, এটি সত্যিই সার্ভলেট কনটেক্সটলিস্টনারে করা উচিত, প্রতি-সার্লেটের ভিত্তিতে নয়, কারণ আপনার জেডিবিসি ড্রাইভারটি আপনার ওয়েব অ্যাপ্লিকেশনে আপনার সমস্ত সার্লেলেট জুড়ে রয়েছে।
ডাইসকগ

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

আমারও অনুরূপ সমস্যা ছিল, তবে অতিরিক্ত আমি যখনই টমক্যাট সার্ভারের সাথে জেএসপি পৃষ্ঠাগুলি সংশোধন / সংরক্ষণ করেছি তখন জাভা হিপ স্পেস ত্রুটি পেয়েছিলাম, সুতরাং প্রসঙ্গটি পুরোপুরি রিচার্জ করা হয়নি।

আমার সংস্করণগুলি অ্যাপাচি টমক্যাট 6.0.29 এবং জেডিকে 6u12 ছিল।

ইউআরএল http://wiki.apache.org/tomcat/ মেমরিলিকপ্রোটেকশন এর রেফারেন্স বিভাগে প্রস্তাবিত হিসাবে জেডিকে 6u21 তে আপগ্রেড করা জাভা হিপ স্পেস সমস্যার সমাধান করেছে (প্রসঙ্গ এখন ঠিক আছে পুনরায় লোড করে) যদিও জেডিবিসি ড্রাইভার ত্রুটি এখনও উপস্থিত রয়েছে।


0

টমক্যাট সংস্করণ 6.026 এর সাথে আমি একই সমস্যাটি পেয়েছি।

আমি মাইএসকিএল জেডিবিসি.জারকে ওয়েবএপিপি লাইব্রেরিতে পাশাপাশি টমক্যাট লিবিতে ব্যবহার করেছি।

টমক্যাট লাইব ফোল্ডারটি থেকে জারটি সরিয়ে উপরেরটি ঠিক করতে।

সুতরাং আমি যা বুঝতে পারি তা হ'ল টোম্যাক্যাট জেডিবিসি মেমরি ফুটোটি সঠিকভাবে পরিচালনা করছে। তবে যদি এমওয়াইএসকিউএল জেডিবিসি জারটি ওয়েব অ্যাপ্লিকেশন এবং টমক্যাট লিবে নকল করা হয়, টমক্যাট কেবল টমক্যাট লিব ফোল্ডারে উপস্থিত জারটি পরিচালনা করতে সক্ষম হবে।


0

আমি যখন এডাব্লুএসে আমার গ্রিল অ্যাপ্লিকেশন স্থাপন করছিলাম তখন আমি এই সমস্যার মুখোমুখি হয়েছি। এটি জেডিবিসি ডিফল্ট ড্রাইভার org.h2 ড্রাইভারের বিষয়। আপনি এটি আপনার কনফিগারেশন ফোল্ডারের ভিতরে ডেটাসোর্স.groovy এ দেখতে পাচ্ছেন। আপনি নীচে দেখতে পারেন:

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

Org.h2.Driver উল্লেখ করা আছে যেখানেই এই লাইনগুলি মন্তব্য করুন the আপনি যদি সেই ডাটাবেসটি ব্যবহার না করেন তবে . ফাইলে । অন্যথায় আপনাকে সেই ডাটাবেস জার ফাইলটি ডাউনলোড করতে হবে।

ধন্যবাদ


0

এই ত্রুটিটি জেটিডিএস ড্রাইভার ১.৩.০ (এসকিউএল সার্ভার) সহ একটি গ্রেইস অ্যাপ্লিকেশনটিতে ঘটেছিল। সমস্যাটি ছিল এসকিউএল সার্ভারে একটি ভুল লগইন। এই সমস্যাটি সমাধানের পরে (এসকিউএল সার্ভারে) আমার অ্যাপটি সঠিকভাবে টমক্যাটে স্থাপন করা হয়েছিল। টিপ: আমি stacktrace.log এ ত্রুটিটি দেখেছি

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.