2014-06-24 6 views
4

오늘 내 웹 응용 프로그램에서 잠재적 인 메모리 누수를 수정하려고했습니다.봄 + MongoDB : 잠재적 인 메모리 누수 메시지

다음 라이브러리를 사용합니다.

  • 스프링 webmvc-3.2.9.RELEASE
  • I 놓친
  • 몽고 - 자바 드라이버 2.12.1

우선 스프링 데이터 MongoDB를-1.5.0.RELEASE MongoClient를 닫지 만이 방법으로 구성을 변경했습니다.

@Configuration 
public class MongoDBConfiguration implements DisposableBean { 
    private MongoClient mongoClient; 

    @Bean 
    public MongoTemplate mongoTemplate() { 
     try { 
      final Properties props = loadProperties(); 
      log.debug("Initializing Mongo DB client"); 
      mongoClient = 
        new MongoClient(getProperty(props, "host", "localhost"), cint(getProperty(props, "port", 
          "27017"))); 
      UserCredentials credentials = null; 
      final String auth = getProperty(props, "auth", null); 
      if (auth != null && auth.equalsIgnoreCase("true")) { 
       final String user = getProperty(props, "user", null); 
       final String pass = getProperty(props, "pass", null); 
       if (user != null && pass != null) { 
        credentials = new UserCredentials(user, pass); 
       } 
      } 
      final MongoDbFactory mongoDbFactory = 
        new SimpleMongoDbFactory(mongoClient, getProperty(props, "dbname", "Feeder"), credentials); 
      final MappingMongoConverter mongoConverter = 
        new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), 
          new MongoMappingContext()); 
      mongoConverter.setCustomConversions(customConversions(mongoConverter)); 
      mongoConverter.afterPropertiesSet(); 
      final MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, mongoConverter); 
      return mongoTemplate; 
     } catch (final IOException e) { 
      log.error("", e); 
     } 
     return null; 
    } 

    /** 
    * close Mongo client to avoid memory leaks 
    */ 
    @Override 
    public void destroy() { 
     log.debug("Shutdown Mongo DB connection"); 
     mongoClient.close(); 
     log.debug("Mongo DB connection shutdown completed"); 
    } 
} 

웹 응용 프로그램을 중지하거나 다시로드 할 때 메모리 누수 가능성에 대한 메시지가 계속 표시됩니다.

2014-06-24 07:58:02,114 DEBUG d.p.f.s.m.MongoDBConfiguration - Shutdown Mongo DB connection 
2014-06-24 07:58:02,118 DEBUG d.p.f.s.m.MongoDBConfiguration - Mongo DB connection shutdown completed 
Jun 24, 2014 7:58:02 AM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks 
SEVERE: The web application [/feeder##1.5.1] created a ThreadLocal with key of type [com.mongodb.BaseCluster$1] (value [[email protected]]) and a value of type [java.util.Random] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 

줄 3과 4는 내가 본 것보다 요금이 9 배가 높습니다.

어떻게 해결할 수 있습니까? 그것을 무시할 수 있습니까?

답변

0

스레드 로컬을 정리해야합니다. 내 대답보기 stop/interrupt a thread after jdbc Driver has been deregister

/** 
* Cleanup function which cleans all thread local variables. Using thread 
* local variables is not a good practice but unfortunately some libraries 
* are still using them. We need to clean them up to prevent memory leaks. 
* 
* @return number of Thread local variables 
*/ 
private int immolate() { 
    int count = 0; 
    try { 
     final Field threadLocalsField = Thread.class 
       .getDeclaredField("threadLocals"); 
     threadLocalsField.setAccessible(true); 
     final Field inheritableThreadLocalsField = Thread.class 
       .getDeclaredField("inheritableThreadLocals"); 
     inheritableThreadLocalsField.setAccessible(true); 
     for (final Thread thread : Thread.getAllStackTraces().keySet()) { 
      count += clear(threadLocalsField.get(thread)); 
      count += clear(inheritableThreadLocalsField.get(thread)); 
     } 
     log.info("Immolated " + count + " values in ThreadLocals"); 
    } catch (Exception e) { 
     log.error("ThreadLocalImmolater.immolate()", e); 
    } 
    return count; 
} 

/** 
* Cleaner for thread local map. 
* 
* @param threadLocalMap 
*   thread local map to clean or null 
* @return number of cleaned objects 
* @throws Exception 
*    in case of error 
*/ 
private int clear(@NotNull final Object threadLocalMap) throws Exception { 
    if (threadLocalMap == null) { 
     return 0; 
    } 
    int count = 0; 
    final Field tableField = threadLocalMap.getClass().getDeclaredField(
      "table"); 
    tableField.setAccessible(true); 
    final Object table = tableField.get(threadLocalMap); 
    for (int i = 0, length = Array.getLength(table); i < length; ++i) { 
     final Object entry = Array.get(table, i); 
     if (entry != null) { 
      final Object threadLocal = ((WeakReference<?>) entry).get(); 
      if (threadLocal != null) { 
       log(i, threadLocal); 
       Array.set(table, i, null); 
       ++count; 
      } 
     } 
    } 
    return count; 
} 
관련 문제