2012-10-04 30 views
2

我目前正在开发与 以下 属性的机器上的Java Web应用程序:阿帕奇Tomcat7内存泄漏(疑单独的对象)

  • Ubuntu的服务器版Linux的12.04 64位
  • 太阳JAVA JDK的版本7
  • 的Apache Tomcat 7.0.30
  • Netbeans的IDE,版本7.1.2

我的项目由一个SOAP Web服务接口组成,该接口维护一个共享内存对象 。为了使该对象对所有线程可见,我开发了一个 单例。我张贴下面我的应用程序的代码:

@WebService() 
public class ETL_WS { 

    private Singleton CAP_offer_coupon_map; 

    public ETL_WS() { } 

    /** 
    * This method adds a single coupon record to the memory map. 
    */ 
    @WebMethod 
    synchronized public int singleCouponLoad(@WebParam(name = 
      "CouponID") long coupon_id, 
      @WebParam(name = "ProductCategoryID") long product_category_id, 
      @WebParam(name = "DateTo") Date dateTo, 
      @WebParam(name = "LocationID") Location location_id) { 
     Coupon _c = new Coupon(coupon_id, product_category_id, dateTo); 
     if(location_id != null) 
      _c.setLocation(location_id); 
     CAP_CouponOfferCollection _data = CAP_offer_coupon_map.getModel(); 
     Coupon _tmp = _data.getCoupon(coupon_id); 
     if(_tmp == null) 
      return -1; 
     _data.insertCoupon(_c); 
     return 0; 
    } 

    /** 
    * This method adds a single offer record to the memory map. 
    */ 
    @WebMethod 
    synchronized public int singleOfferLoad(@WebParam(name = 
      "OfferID") long offer_id, 
      @WebParam(name = "ProductCategoryID") long product_category_id, 
      @WebParam(name = "DateTo") Date dateTo, 
      @WebParam(name = "LocationID") Location location_id) { 
     Offer _o = new Offer(offer_id, product_category_id, dateTo); 
     if(location_id != null) 
      _o.setLocation(location_id); 
     CAP_CouponOfferCollection _data = CAP_offer_coupon_map.getModel(); 
     Offer _tmp = _data.getOffer(offer_id); 
     if(_tmp == null) 
      return -1; 
     _data.insertOffer(_o); 
     return 0; 
    } 

    @WebMethod 
    synchronized public String getAllCoupons() { 
     CAP_CouponOfferCollection _data = CAP_offer_coupon_map.getModel(); 
     HashMap<Long, Coupon> _c = _data.getCoupons_map(); 
     return _c.toString(); 
    } 

    @WebMethod 
    synchronized public String getAllOffers() { 
     CAP_CouponOfferCollection _data = CAP_offer_coupon_map.getModel(); 
     HashMap<Long, Offer> _o = _data.getOffers_map(); 
     return _o.toString(); 
    } 

    @WebMethod 
    synchronized public long getProductIdFromCouponId(@**WebParam(name 
      = "CouponID") long coupon_id) { 
     long _product_id = -1; 
     CAP_CouponOfferCollection _data = CAP_offer_coupon_map.getModel(); 
     Coupon _c = _data.getCoupon(coupon_id); 
     if(_c != null) 
      _product_id = _c.getCoupon_id(); 
     return _product_id; 
    } 

    @WebMethod 
    synchronized public long getProductIdFromOfferId(@WebParam(name = "OfferID") long 
      offer_id) { 
     long _product_id = -1; 
     CAP_CouponOfferCollection _data = CAP_offer_coupon_map.getModel(); 
     Offer _o = _data.getOffer(offer_id); 
     if(_o != null) 
      _product_id = _o.getOffer_id(); 
     return _product_id; 
    } 

} 

的辛格尔顿包装类如下所示:

public class Singleton { 

    private static boolean _instanceFlag = false; 

    private static final Singleton _instance = new Singleton(); 

    private static CAP_CouponOfferCollection _data; 

    private Singleton() { 
    _data = new CAP_CouponOfferCollection(); 
    _instanceFlag = true; 
    } 

    public static synchronized CAP_CouponOfferCollection getModel() { 
    if(_instanceFlag == false) { 
     _data = new CAP_CouponOfferCollection(); 
     _instanceFlag = true; 
    } 
    return _data; 
    } 
} 

和CAP_CouponOfferCollection类如下所示:

public class CAP_CouponOfferCollection { 

    private HashMap<Long, Coupon> _coupons_map; 

    private HashMap<Long, ArrayList<Long>> _product_to_coupons_map; 

    private HashMap<Long, Offer> _offers_map; 

    private HashMap<Long, ArrayList<Long>> _product_cat_to_offers_map; 

    private static long _creation_time; 

    public CAP_CouponOfferCollection() { 
     _creation_time = System.currentTimeMillis(); 
     System.out.println("Creation of CAP_CouponOffer object: " + 
      _creation_time); 
    } 

    synchronized public void insertCoupon(Coupon newCoupon) { 
     if(_coupons_map == null) { 
      _coupons_map = new HashMap<Long, Coupon>(); 
      _product_to_coupons_map = 
        new HashMap<Long, ArrayList<Long>>(); 
     } 
     Long key = newCoupon.getCoupon_id(); 
     if(!_coupons_map.containsKey(key)) { 
      _coupons_map.put(key, newCoupon); 
      key = newCoupon.getProductCategory_id(); 
      if(_product_to_coupons_map.containsKey(key)) { 
       ArrayList<Long> _c_list = _product_to_coupons_map.get(key); 
       _c_list.add(newCoupon.getCoupon_id()); 
       _product_to_coupons_map.remove(key); 
       _product_to_coupons_map.put(key, _c_list); 
      }else { 
       ArrayList<Long> _c_list = new ArrayList<Long>(); 
       _c_list.add(newCoupon.getCoupon_id()); 
       _product_to_coupons_map.put(key, _c_list); 
      } 
     } 
    } 

    synchronized public void insertOffer(Offer newOffer) { 
     if(_offers_map == null) { 
      _offers_map = new HashMap<Long, Offer>(); 
      _product_cat_to_offers_map = 
        new HashMap<Long, ArrayList<Long>>(); 
     } 
     Long key = newOffer.getOffer_id(); 
     if(!_offers_map.containsKey(key)) { 
      _offers_map.put(key, newOffer); 
      key = newOffer.getProductCategory_id(); 
      if(_product_cat_to_offers_map.containsKey(key)) { 
       ArrayList<Long> _o_list = _product_cat_to_offers_map.get(key); 
       _o_list.add(newOffer.getOffer_id()); 
       _product_cat_to_offers_map.remove(key); 
       _product_cat_to_offers_map.put(key, _o_list); 
      }else { 
       ArrayList<Long> _o_list = new ArrayList<Long>(); 
       _o_list.add(newOffer.getOffer_id()); 
       _product_cat_to_offers_map.put(key, _o_list); 
      } 
     } 
    } 

    synchronized public void removeCoupon(long couponId) { 
     Coupon _c; 
     Long key = new Long(couponId); 
     if(_coupons_map != null && _coupons_map.containsKey(key)) { 
      _c = (Coupon) _coupons_map.get(key); 
      _coupons_map.remove(key); 
      Long product = new Long(_c.getCoupon_id()); 
      ArrayList<Long> _c_list = 
        (ArrayList<Long>) _product_to_coupons_map.get(product); 
      _c_list.remove(key); 
      _product_to_coupons_map.remove(product); 
      _product_to_coupons_map.put(product, _c_list); 
     } 
    } 

    synchronized public void removeOffer(long offerId) { 
     Offer _o; 
     Long key = new Long(offerId); 
     if(_offers_map != null && _offers_map.containsKey(key)) { 
      _o = (Offer) _offers_map.get(key); 
      _offers_map.remove(key); 
      Long product = new Long(_o.getOffer_id()); 
      ArrayList<Long> _o_list = 
        (ArrayList<Long>) _product_cat_to_offers_map.get(product); 
      _o_list.remove(key); 
      _product_cat_to_offers_map.remove(product); 
      _product_cat_to_offers_map.put(product, _o_list); 
     } 
    } 

    synchronized public Coupon getCoupon(long CouponID) { 
     Long key = new Long(CouponID); 
     if(_coupons_map != null && _coupons_map.containsKey(key)) { 
      Coupon _c = (Coupon) _coupons_map.get(key); 
      Date _now = new Date(); 
      if(_now.compareTo(_c.getDateTo()) > 0) { 
       this.removeCoupon(CouponID); 
       return null; 
      } 
      return (Coupon) _coupons_map.get(key); 
     }else 
      return null; 
    } 

    synchronized public Offer getOffer(long OfferID) { 
     Long key = new Long(OfferID); 
     if(_offers_map != null && _offers_map.containsKey(key)) { 
      Offer _o = (Offer) _offers_map.get(key); 
      Date _now = new Date(); 
      if(_now.compareTo(_o.getDateTo()) > 0) { 
       this.removeOffer(OfferID); 
       return null; 
      } 
      return (Offer) _offers_map.get(key); 
     }else 
      return null; 
    } 

    synchronized public ArrayList<Long> getCoupons(long ProductID) { 
     Long key = new Long(ProductID); 
     if(_product_to_coupons_map != null && _product_to_coupons_map.containsKey(key)) 
     { 
      ArrayList<Long> _c_list = 
        (ArrayList<Long>) _product_to_coupons_map.get(key); 
      Iterator itr = _c_list.iterator(); 
      while(itr.hasNext()) { 
       Long l = (Long) itr.next(); 
       if(this.getCoupon(l.longValue()) == null) 
        _c_list.remove(l.intValue()); 
      } 
      _product_to_coupons_map.remove(key); 
      _product_to_coupons_map.put(key, _c_list); 
      return _c_list; 
     }else 
      return null; 
    } 

    synchronized public ArrayList<Long> getOffers(long ProductID) { 
     Long key = new Long(ProductID); 
     if(_product_cat_to_offers_map != null && 
       _product_cat_to_offers_map.containsKey(key)) { 
      ArrayList<Long> _o_list = _product_cat_to_offers_map.get(key); 
      Iterator itr = _o_list.iterator(); 
      while(itr.hasNext()) { 
       Long l = (Long) itr.next(); 
       if(this.getOffer(l.longValue()) == null) 
        _o_list.remove(l.intValue()); 
      } 
      _product_cat_to_offers_map.remove(key); 
      _product_cat_to_offers_map.put(key, _o_list); 
      return _o_list; 
     }else 
      return null; 
    } 

    synchronized public HashMap<Long, Coupon> getCoupons_map() { 
     return _coupons_map; 
    } 

    synchronized public void setCoupons_map(HashMap<Long, Coupon> _coupons_map) { 
     this._coupons_map = _coupons_map; 
    } 

    synchronized public static long getCreation_time() { 
     return _creation_time; 
    } 

    synchronized public void cleanup_offers() { 
     if(_product_cat_to_offers_map != null) { 
      Set _offers_key_set = _product_cat_to_offers_map.keySet(); 
      Iterator itr = _offers_key_set.iterator(); 
      while(itr.hasNext()) { 
       Long l = (Long) itr.next(); 
       this.getOffers(l.longValue()); 
      } 
     } 
    } 

    synchronized public void cleanup_coupons() { 
     if(_product_to_coupons_map != null) { 
      Set _coupons_key_set = _product_to_coupons_map.keySet(); 
      Iterator itr = _coupons_key_set.iterator(); 
      while(itr.hasNext()) { 
       Long l = (Long) itr.next(); 
       this.getCoupons(l.longValue()); 
      } 
     } 
    } 
} 

的问题是当我部署的上述申请(其名称为ETL_Procedures) 到的Apache Tomcat我得到以下严重日志条目:

SEVERE: The web application [/ETL_Procedures] appears to have started a thread named [maintenance-task-executor-thread-1] but has failed to stop it. This is very likely to create a memory leak. 
Oct 03, 2012 5:35:03 PM org.apache.catalina.loader.WebappClassLoadercheckThreadLocalMapForLeaks 
SEVERE: The web application [/ETL_Procedures] created a ThreadLocal with key of type [org.glassfish.gmbal.generic.OperationTracer$1] (value [[email protected]]) and a value of type [java.util.ArrayList] (value [[]]) 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. 
Oct 03, 2012 5:35:03 PM org.apache.catalina.loader.WebappClassLoadercheckThreadLocalMapForLeaks 
SEVERE: The web application [/ETL_Procedures] created a ThreadLocal with key of type [com.sun.xml.bind.v2.ClassFactory$1] (value [[email protected]]) and a value of type [java.util.WeakHashMap] (value [{class com.sun.xm[email protected]5b73a116, class javax.xml.bind.annotat[email protected]454da42, class com.su[email protected]5ec52546, class com.sun.xml.[email protected]61124745, class [email protected], class com.[email protected]76cd7a1f, class java[email protected]2c0cc628, class com.sun.xml.w[email protected]7aa582af}]) 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. 
Oct 03, 2012 5:35:03 PM org.apache.catalina.loader.WebappClassLoadercheckThreadLocalMapForLeaks 
SEVERE: The web application [/ETL_Procedures] created a ThreadLocal with key of type [com.sun.xml.bind.v2.runtime.Coordinator$1] (value [[email protected]]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@33d7a245]) 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. 
Oct 03, 2012 5:35:03 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks 
SEVERE: The web application [/ETL_Procedures] created a ThreadLocal with key of type [org.glassfish.gmbal.generic.OperationTracer$1] (value [[email protected]]) and a value of type [java.util.ArrayList] (value [[]]) 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. 

我真的不知道是什么原因导致这些内存泄漏。我的问题是 如下:

  1. 谁能怀疑什么可能是与我的web服务的问题?如果 原因的内存泄漏的是Singleton对象, 还有什么能做些什么来满足我的应用需求,并避免内存 泄漏。
  2. 有,我可以为了用它来监视我的线程的任何工具, 究竟是什么原因导致这些严重的消息?
  3. 如果我让我的应用程序部署时间长,我得到一个 IllegalStateException异常以下消息:

    INFO: Illegal access: this web application instance has been stopped already. Could not load com.sun.xml.ws.rx.rm.localization.LocalizationMessages. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact. 
    java.lang.IllegalStateException at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600) 
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559) 
    at com.sun.xml.ws.rx.rm.runtime.sequence.SequenceMaintenanceTask.run(SequenceMaintenanceTask.java:81) 
    at com.sun.xml.ws.commons.DelayedTaskManager$Worker.run(DelayedTaskManager.java:91) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
    at java.lang.Thread.run(Thread.java:722) 
    

我怎么能看到导致该异常整个呼叫路径?

谢谢您的时间和我的长消息真的很抱歉。

+1

如果您怀疑内存泄漏,我建议您在应用程序上使用内存分析器。它通常比猜测问题可能更有用。 –

+0

我现在正在学习如何进行配置:-)。感谢您的关注和您的快速回答。你发现我的类实现有什么问题吗?我知道这是一个普遍的问题,但在深入细节之前,有经验的开发人员的意见是值得欢迎的。 –

+0

许多事情可以改善恕我直言,但没有可能会导致错误。很可能你的问题不在这个代码中,这就是为什么你需要一个分析器来帮助你指出它。 –

回答

1

看起来就像你java.lang.IllegalStateException当应用程序重新部署,但未能取消部署,和一些老过程中仍然运行。也许当您重新部署应用程序时,某些线程正在等待,而其他线程离开synchronization块。也许这是一些预定的过程,你有什么?很难说这是什么。

我可以建议你在web.xml中注册监听器,并在contextDestroyed()方法中清理所有资源。并运行一些内存分析工具,例如,MAT

+0

您可以发布一个链接,指导您在web.xml中注册监听器吗?这将是非常有益的。感谢您的关注。 –

+1

http://www.javabeat.net/2009/02/servletcontextlistener-example/ – user1516873

+0

因此,通过使用上下文侦听器,我可以将我的Singleton对象用作所有Web服务调用的全局对象?此外,它会在我的web应用程序启动时创建,并且当我的web应用程序停止时它将被销毁?不好意思问这么多问题,但正如你所看到的,我还在学习:-)。 –