2010-05-20 25 views
33

मैं बिल्ला के तहत चल रहे webapps का एक संग्रह है। टॉमकैट को -Xmx तर्क का उपयोग करके 2 जीबी मेमोरी रखने के लिए कॉन्फ़िगर किया गया है।जावा Runtime.getRuntime()। कार्यकारी() विकल्प

webapps में से कई एक काम है कि निम्नलिखित कोड का इस्तेमाल कर रही समाप्त होता है प्रदर्शन करने की जरूरत है:

Runtime runtime = Runtime.getRuntime(); 
Process process = runtime.exec(command); 
process.waitFor(); 
... 

मुद्दा हम कर रहे हैं जिस तरह से है कि यह "बाल-प्रक्रिया" बनाया जा रहा है से संबंधित है लिनक्स पर (Redhat 4.4 और Centos 5.4)।

यह मेरी समझ है कि टोमकैट की मात्रा के बराबर स्मृति की मात्रा प्रारंभिक रूप से इस बच्चे की प्रक्रिया के लिए भौतिक (गैर-स्वैप) सिस्टम मेमोरी के पूल में मुक्त होने की आवश्यकता है। हम पर्याप्त खाली भौतिक स्मृति की जरूरत नहीं है, तो हम इस हो रही है:

java.io.IOException: error=12, Cannot allocate memory 
    at java.lang.UNIXProcess.<init>(UNIXProcess.java:148) 
    at java.lang.ProcessImpl.start(ProcessImpl.java:65) 
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:452) 
    ... 28 more 

मेरे प्रश्न हैं:

1) स्मृति की राशि माता पिता के बराबर के लिए आवश्यकता को दूर करने के क्या यह संभव है भौतिक स्मृति में प्रक्रिया मुक्त हो रही है? मैं एक जवाब मुझे कितनी स्मृति बच्चे प्रक्रिया हो जाता है निर्दिष्ट करने के लिए या स्वैप स्मृति का उपयोग करने के लिए लिनक्स पर जावा अनुमति देने के लिए अनुमति देता है के लिए देख रहा हूँ।

2) Runtime.getRuntime()। Exec() के विकल्प क्या हैं यदि # 1 का कोई समाधान मौजूद नहीं है? मैं केवल दो के बारे में सोच सकता हूं, जिनमें से कोई भी वांछनीय नहीं है। JNI (बहुत अन-वांछनीय) या पुनर्लेखन कार्यक्रम हम जावा में बुला रहे हैं और यह अपने आप प्रक्रिया है कि किसी भी तरह webapp के साथ संचार कर रही है। दूसरों को होना है।

3) इस समस्या यह है कि मैं नहीं दिखाई दे रहा है कि संभावित इसे ठीक कर सकता है के लिए एक और पक्ष है? टोमकैट द्वारा उपयोग की जाने वाली मेमोरी की मात्रा को कम करना एक विकल्प नहीं है। सर्वर पर मेमोरी बढ़ाना हमेशा एक विकल्प होता है, लेकिन बैंड-एड्स की तरह लगता है।

सर्वर जावा चल रहे हैं 6.

संपादित करें: मुझे लगता है कि मैं एक बिल्ला विशिष्ट सुधार के लिए नहीं देख रहा हूँ निर्दिष्ट करना चाहिए। वेबसर्वर पर चल रहे किसी भी जावा एप्लिकेशन के साथ यह समस्या देखी जा सकती है (कई हैं)। मैंने बस उदाहरण के रूप में टोमकैट का उपयोग किया क्योंकि इसकी सबसे अधिक संभावना है कि इसे आवंटित किया जाए और यह वह जगह है जहां हमने वास्तव में पहली बार त्रुटि देखी थी। यह एक प्रतिलिपि त्रुटि है।

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

+1

संबंधित: http://stackoverflow.com/questions/209875/from-what-linux- कर्नेल- libc-version-is-java-runtime-exec-safe-with-regards-to-m – BalusC

+0

मैंने नहीं किया ' वास्तव में उस लेख में कुछ भी नहीं देखता जिसने मेरे सवालों का जवाब दिया। मैंने देखा कि एक क्रिया "मूल प्रक्रिया द्वारा उपयोग की जाने वाली स्मृति की मात्रा को कम करें" (हमारे लिए कोई विकल्प नहीं) चाहे उलिमिट या जावा ऑप्ट्स के साथ। दूसरा ल्यूक के उत्तर के समान था, जो एक अलग प्रक्रिया है जो कम स्मृति का उपयोग करता है। यह आदर्श से बहुत दूर है, लेकिन कम से कम व्यावहारिक – twilbrand

+0

आप किस जेवीएम का उपयोग कर रहे हैं (सूर्य, ओपनजेडीके ...?) इससे मदद नहीं मिलती है? http://stackoverflow.com/questions/1124771/how-to-solve-java-io-ioexception-error12-cannot-allocate-memory-calling-runt – leonbloy

उत्तर

5

एक ProcessBuilder का उपयोग करें। डॉक्स का कहना है कि इन दिनों उप-प्रक्रिया शुरू करने का "पसंदीदा" तरीका है। आपको नई प्रक्रिया के लिए मेमोरी भत्ते निर्दिष्ट करने के लिए पर्यावरण मानचित्र (लिंक में लिंक हैं) का उपयोग करने पर भी विचार करना चाहिए। मुझे संदेह है (लेकिन निश्चित रूप से कुछ नहीं पता) कि इतनी मेमोरी की आवश्यकता है कि यह टोमकैट प्रक्रिया से सेटिंग्स को विरासत में ले रहा है। पर्यावरण मानचित्र का उपयोग करने से आपको उस व्यवहार को ओवरराइड करने की अनुमति मिलनी चाहिए। हालांकि, ध्यान दें कि एक प्रक्रिया शुरू करना बहुत ओएस विशिष्ट है, इसलिए वाईएमएमवी।

+0

मैंने प्रोसेसबिल्डर पर विशेष रूप से पर्यावरण को संशोधित करने की क्षमता देखी है। आप वास्तव में रनटाइम के साथ भी ऐसा कर सकते हैं। हालांकि, प्रारंभिक स्मृति को कम रखने के लिए मुझे वास्तव में पर्यावरण परिवर्तनीय परिवर्तन के बारे में कोई जानकारी नहीं मिली। मैंने कुछ प्रक्रियाओं के मौजूदा वातावरण को मुद्रित किया और स्मृति संशोधित पैरामीटर स्पष्ट नहीं था। क्या आप बता सकते हैं कि मैं पर्यावरण चर के साथ स्मृति आवंटन को कैसे नियंत्रित कर सकता हूं?लिनक्स में विशेष रूप से? – twilbrand

+3

जहां तक ​​मैं समझता हूं, 'प्रोसेसबिल्डर' लिनक्स पर समान स्मृति बाधाओं से ग्रस्त है। – kongo09

+2

इस कारण बहुत मेमोरी की आवश्यकता है कि एक नई प्रक्रिया को कताई के लिए मानक 'कांटा' एल्गोरिदम निष्पादन प्रक्रिया को पूरी तरह से डुप्लिकेट करने का कारण बनता है, अस्थायी रूप से। ऐसा कहा जाता है कि उप-प्रक्रियाओं को लॉन्च करने वाला यह एकमात्र क्रॉस-प्लेटफ़ॉर्म तरीका है। जहां तक ​​मैं बाहर निकलने में सक्षम हूं, प्रोसेसबिल्डर केवल सुविधा प्रदान करता है - यह वास्तव में इसे हल नहीं करता है। – robert

2

मुझे लगता है कि यह एक यूनिक्स कांटा() मुद्दा है, स्मृति आवश्यकता रास्ता कांटा (वे से आता है) काम करता है - यह पहली क्लोन बच्चे प्रक्रिया छवि (जो आकार में यह वर्तमान में है) तो माता-पिता की छवि को बदल देता है बच्चे की छवि के साथ।मुझे सोलारिस पर पता है कि इस व्यवहार को नियंत्रित करने का कोई तरीका है, लेकिन मुझे पता नहीं है कि यह क्या है।

अद्यतन: यह पहले से ही From what Linux kernel/libc version is Java Runtime.exec() safe with regards to memory?

+0

मैंने वास्तव में उस लेख में कुछ भी नहीं देखा जो मेरे सवालों का जवाब देता था। मैंने देखा कि एक क्रिया "मूल प्रक्रिया द्वारा उपयोग की जाने वाली स्मृति की मात्रा को कम करें" (हमारे लिए कोई विकल्प नहीं) चाहे उलिमिट या जावा ऑप्ट्स के साथ। दूसरा ल्यूक के उत्तर के समान था, जो एक अलग प्रक्रिया है जो कम स्मृति का उपयोग करता है। यह आदर्श से बहुत दूर है, लेकिन कम से कम व्यावहारिक है। – twilbrand

5

से समझाया गया है कि मैं इस article एक समाधान के पाया, मूल रूप से विचार यह है कि आप (अपने आवेदन के स्टार्टअप है कि आप के साथ संवाद में जल्दी पर एक प्रक्रिया बनाने के इनपुट के माध्यम से धाराएं) और फिर उस उपप्रोसेस आपके लिए आपके आदेश निष्पादित करता है।

//you would probably want to make this a singleton 
public class ProcessHelper 
{ 
    private OutputStreamWriter output; 
    public ProcessHelper() 
    { 
     Runtime runtime = Runtime.getRuntime(); 
     Process process = runtime.exec("java ProcessHelper"); 
     output = new OutputStreamWriter(process.getOutputStream()); 
    } 
    public void exec(String command) 
    { 
     output.write(command, 0, command.length()); 
    } 
} 

तो आप एक सहायक जावा कार्यक्रम बनाना होगा

public class ProcessHelper 
{ 
    public static void main(String[] args) 
    { 
     BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 
     String command; 
     while((command = in.readLine()) != null) 
     { 
      Runtime runtime = Runtime.getRuntime(); 
      Process process = runtime.exec(command); 
     } 
    } 
} 

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

आप अपने प्रोटोकॉल को गहराई से थोड़ा और भी बना सकते हैं, जैसे एक्जिटकोड लौटाना, त्रुटियों की सूचना देना आदि।

+0

यह वेबपैप के लिए उचित रूप से काम नहीं करेगा। वेबपैप किसी भी समय सर्वर चलने के दौरान तैनात किया जाता है - उस समय स्मृति की किसी भी मात्रा का उपभोग करता है। –

+0

@ आर्न बर्मेस्टर - यह सच है, यदि आप इसे साझा टॉमकैट उदाहरण पर चला रहे हैं तो आपके पास इस रन के दौरान प्रक्रिया के लिए आवंटित रूप से बड़ी मात्रा में आवंटित हो सकता है। लेकिन अगर आप एक गैर-साझा टॉमकैट सर्वर पर चल रहे हैं (यह एकमात्र एप्लीकेशन है) और आप इसे निष्पादित करने के लिए एप्लिकेशन स्टार्टअप में शामिल हो सकते हैं, इसे काम करना चाहिए। – luke

+0

जैसा कि मैंने हाल ही में ऊपर बताया है, मैं टॉमकैट विशिष्ट उत्तर की तलाश नहीं कर रहा हूं। हमारे पास कई वेबपैप्स के साथ-साथ कई अन्य जावा प्रक्रियाओं के साथ टोमकैट है जो सभी संभावित रूप से एक ही समस्या को देख सकते हैं। – twilbrand

1

इससे मुझे लगता है कि यह मदद करेगा। मुझे पता है कि यह एक पुराना धागा है, सिर्फ भविष्य के लिए ... http://wrapper.tanukisoftware.com/doc/english/child-exec.html

+0

दुर्भाग्य से, यह व्यावसायिक संस्करण का हिस्सा है, जो महंगा है, अगर यह एकमात्र चीज है जिसे आपको कभी भी चाहिए। क्या आप किसी भी मुफ्त विकल्प के बारे में जानते हैं? – kongo09

+0

तनुकी रैपर के लिए यह निःशुल्क विकल्प आज़माएं: http://sourceforge.net/projects/yajsw/forums/forum/810311/topic/4423982 – kongo09

1

एक और विकल्प एक अलग निष्पादन प्रक्रिया चलाना है जो या तो फ़ाइल या किसी अन्य प्रकार की "कतार" देखता है। आप उस वांछित कमांड को उस फ़ाइल में जोड़ते हैं, और निष्पादन सर्वर इसे स्पॉट करता है, कमांड चलाता है, और किसी भी तरह से परिणाम किसी अन्य स्थान पर लिखता है जिसे आप प्राप्त कर सकते हैं।

+0

कुंजी यह है कि निष्पादित उपभोक्ता प्रक्रिया के पास एक छोटा पदचिह्न है, और इस प्रकार बिना कांटा जा सकता है मुद्दे। – Muhd

+0

किसी फ़ाइल या अन्य सार्वजनिक रूप से दृश्यमान प्रविष्टि बिंदु का उपयोग करना ऐसा लगता है जैसे यह सुरक्षा समस्याओं को पेश कर सकता है, है ना? एक हमलावर को आपके उपयोगकर्ता के रूप में मनमाने ढंग से कोड निष्पादित करने देना (इस मामले में tomcat उपयोगकर्ता)। कुछ प्रकार के प्रमाणीकरण प्रोटोकॉल के साथ एक सॉकेट बेहतर हो सकता है। और व्यवहार में, वह प्रमाणीकरण प्रोटोकॉल एसएसएच भी हो सकता है ... – Jolta

1

अब तक का सबसे अच्छा समाधान सार्वजनिक चाबियों के साथ सुरक्षित खोल का उपयोग कर रहा था। http://www.jcraft.com/jsch/ का उपयोग करके मैंने स्थानीयहोस्ट से कनेक्शन बनाया और इस तरह के आदेशों को निष्पादित किया। हो सकता है कि इसमें थोड़ी अधिक उपर है लेकिन मेरी स्थिति के लिए यह एक आकर्षण की तरह काम करता है।

संबंधित मुद्दे