2009-04-01 13 views
9

मेरे जावा एप्लिकेशन में धीमी मेमोरी लीक है। मैं सोच रहा था कि यह इस्तेमाल होने पर हमेशा Entitymanager को बंद न करने के कारण हो सकता है। हालांकि MyEclipse का उपयोग कर डीबी कोड उत्पन्न करने के लिए, मैं इस तरह के तरीकों हो रही है:Entitymanager मेमोरी रिसाव का कारण बनता है?

public Meit update(Meit entity) { 
    logger.info("updating Meit instance"); 
    try { 
     Meit result = getEntityManager().merge(entity); 
     logger.info("update successful"); 
     return result; 
    } catch (RuntimeException re) { 
     logger.error("update failed"); 
     throw re; 
    } 
} 

कौन सा EntityManager बंद कभी नहीं। इसे ध्यान में रखते हुए कोड उत्पन्न होता है, मैं सोच रहा हूं कि कौन सही है, मुझे या आईडीई।

उत्तर

1

एंटिटी प्रबंधकों को आमतौर पर एप्लिकेशन के समान जीवन चक्र होना चाहिए और प्रति-अनुरोध आधार पर बनाया या नष्ट नहीं किया जाना चाहिए।

आपकी "मेमोरी लीक" कैशिंग जेपीए कर रही है उससे कहीं ज्यादा कुछ नहीं हो सकती है। आप यह नहीं कहते कि आप किस जेपीए प्रदाता का उपयोग करते हैं लेकिन मुझे अनुभव से पता है कि डिफ़ॉल्ट रूप से एक्लिप्ससेंक व्यापक कैशिंग (जो जेपीए के कथित लाभों का हिस्सा है और सामान्य रूप से ओआरएम का हिस्सा है)।

आप कैसे जानते हैं कि आपके पास मेमोरी लीक है?

+0

मैं जानता हूँ कि मैं एक स्मृति रिसाव क्योंकि एप्लिकेशन हर कुछ हफ्तों में दुर्घटनाग्रस्त हो जाता है और स्मृति त्रुटियों से बाहर निकलता है। यह एक वेब ऐप है। मैं eclipselink का उपयोग कर रहा हूँ। मैंने सोचा कि ईएम को बंद किया जाना चाहिए: http://stackoverflow.com/questions/220374/do-i-have-to-close-every-entitymanager – GBa

+0

क्या आप हाथ से ईएमएफ बना रहे हैं? एक वेब ऐप में आपको इसे स्वीकार किए जाने वाले उत्तर की तरह इंजेक्शन देना चाहिए, इस मामले में आपको हाथ से इसे बनाना या बंद नहीं करना चाहिए।क्या इस तस्वीर में वसंत है? – cletus

+0

मैं टोमकैट का उपयोग कर रहा हूं, इसलिए इसे इंजेक्शन नहीं दिया जा सकता क्योंकि कोई ईजेबी नहीं है। मैं ईएम बनाने के लिए एक EntityManagerFactory का उपयोग कर रहा हूँ। मैं अनुमान लगा रहा हूं कि सत्र समाप्त हो जाने के बाद, इन्हें साफ नहीं किया जा रहा है। – GBa

1

चेक कि क्या यह सच में एक leak

है यदि ऐसा है तो the Eclipse Memory Analyzer हो और यह विश्लेषण।

ब्लॉग पोस्ट here भी उपयोगी हो सकता है।

0

ऐसा लगता है कि आप एक प्रबंधित प्रबंधित EntityManager का उपयोग कर रहे हैं। आपको EntityManager को अपने आप बंद करने की आवश्यकता होगी, यह spec का हिस्सा है। जब आप अपना वेबपैप बंद करते हैं तो आपको EntityManagerFactory को बंद करने की भी आवश्यकता होगी।

मैं आपके लिए EntityManager/EntityMangerFactory का प्रबंधन करने के लिए OpenEJB या Springframework जैसे कुछ का उपयोग करने की अनुशंसा करता हूं।

6

जैसा कि @Ruggs ने कहा है कि यदि आप EntityManager लाइफसाइक्ल का प्रबंधन कर रहे हैं (जैसा कि जेपीईई द्वारा किए गए सीएमपी कंटेनर प्रबंधित दृढ़ता के विपरीत है) तो आपको इकाई को अलग करने के लिए स्वयं को EntityManager बंद करना होगा या कम से कम EntityManager.clear() पर कॉल करना होगा।

EntityManager हल्के ऑब्जेक्ट हैं इसलिए केवल एक होने की आवश्यकता नहीं है, आप प्रत्येक लेनदेन के लिए एक बना सकते हैं और लेनदेन के बाद इसे बंद कर सकते हैं।

सभी संस्थाओं है कि लोड/एक EntityManager के माध्यम से जारी रहती है जब तक आप स्पष्ट रूप से इसे से (EntityManager.detach() या EntityManager.clear() या EntityManager.close() के माध्यम से) संस्थाओं को अलग स्मृति में रहते हैं। इसलिए अल्पकालिक एंटीटीमेनर्स होना बेहतर है। यदि आप ओओएमई प्राप्त करने के बाद उन्हें अलग किए बिना एक ही EntityManager के माध्यम से 1000000 इकाइयां बनाते हैं (इससे कोई फर्क नहीं पड़ता कि आप प्रत्येक इकाई को अपनी इकाई ट्रांज़ेक्शन में रखते हैं)।

यह सब इस पोस्ट में http://javanotepad.blogspot.com/2007/06/how-to-close-jpa-entitymanger-in-web.html समझाया गया है।

एक उदाहरण (पहले पद से लिया गया) यदि आप से बचने के लिए "स्मृति लीक" आप इस तरह कुछ करना चाहिए (आप सीएमपी का उपयोग नहीं कर रहे हैं) चाहते हैं के रूप में:

EntityManager em = emf.createEntityManager(); 

try { 
    EntityTransaction t = em.getTransaction(); 
    try { 
    t.begin(); 
    // business logic to update the customer 
    em.merge(cust); 
    t.commit(); 
    } finally { 
    if (t.isActive()) t.rollback(); 
    } 
} finally { 
    em.close(); 
}