Java सिस्टम प्रोग्रामिंग: जब "भारी" भाषा हल्का टूल बन जाती है
\n\nजब आप "सिस्टम प्रोग्रामिंग" सुनते हैं, तो आमतौर पर C, असेंबली, पॉइंटर्स और मैन्युअल मेमोरी मैनेजमेंट का ख्याल आता है। Java आखिरी चीज़ है जो दिमाग में आती है। लेकिन यह गलत है। बीस साल से अधिक के विकास के बाद, Java "एंटरप्राइज़ वेबसाइटों के लिए धीमा राक्षस" से एक पूर्ण सिस्टम प्रोग्रामिंग टूल बन गया है - सिस्टम यूटिलिटीज़, नेटवर्क डेमॉन, रिसोर्स मॉनिटरिंग और यहाँ तक कि ऑपरेटिंग सिस्टम कम्पोनेंट लिखने के लिए।
\n\nबेशक, Java ग्राफ़िक्स कार्ड ड्राइवर लिखने में C की जगह नहीं ले सकता। लेकिन सिस्टम प्रोग्रामिंग के 90% कार्यों के लिए - प्रोसेस, फ़ाइल डिस्क्रिप्टर, नेटवर्क सॉकेट, OS-स्तरीय मेमोरी मैनेजमेंट - Java एक सुरुचिपूर्ण, सुरक्षित और क्रॉस-प्लेटफ़ॉर्म समाधान प्रदान करता है। इस लेख में, हम वास्तविक उदाहरणों के साथ Java सिस्टम प्रोग्रामिंग सीखेंगे और दिखाएंगे कि Java कोड C++ जितना ही प्रभावी हो सकता है, लेकिन कहीं अधिक पढ़ने योग्य।
\n\nJava सिर्फ "एंटरप्राइज़" के लिए क्यों नहीं है?
\n\nमुख्य स्टीरियोटाइप: Java गार्बेज कलेक्शन और वर्चुअल मशीन के कारण धीमा है। यह 2004 में सच था। आज JVM मशीन कोड कम्पाइलेशन (JIT), ब्रांच प्रेडिक्शन और मिलीसेकंड से कम पॉज़ वाले जनरेशनल गार्बेज कलेक्शन का उपयोग करता है। सिस्टम प्रोग्रामिंग के लिए तीन चीज़ें महत्वपूर्ण हैं:
\n\n- \n
- क्रॉस-प्लेटफ़ॉर्म — एक ही यूटिलिटी Linux, Windows और macOS पर बिना रीकम्पाइल किए चलती है। \n
- मेमोरी सुरक्षा — कोई segfault नहीं, कोई मेमोरी लीक नहीं (क्लासिकल अर्थ में)। \n
- समृद्ध स्टैंडर्ड लाइब्रेरी — प्रोसेस, NIO, सॉकेट, फ़ाइल चैनल — सब कुछ बिल्ट-इन है। \n
यही गुण Java को सिस्टम यूटिलिटीज़ लिखने के लिए एक बेहतरीन विकल्प बनाते हैं जो स्थिर और पूर्वानुमानित रूप से काम करती हैं।
\n\nप्रोसेस के साथ काम: ProcessBuilder और Runtime.exec
\n\nकोई भी सिस्टम यूटिलिटी देर-सबेर बाहरी प्रोग्राम चलाती है। Java में इसके लिए Runtime.exec() और अधिक लचीला ProcessBuilder जिम्मेदार हैं। दूसरा बेहतर है: यह एनवायरनमेंट, वर्किंग डायरेक्टरी को नियंत्रित करने और I/O स्ट्रीम को रीडायरेक्ट करने की अनुमति देता है।
उदाहरण: मेमोरी उपयोग की निगरानी (Linux)
\n\nमान लीजिए हम उपयोग की गई RAM का प्रतिशत प्राप्त करना चाहते हैं। मैन्युअल रूप से /proc/meminfo पार्स करने के बजाय, हम free चला सकते हैं और आउटपुट प्रोसेस कर सकते हैं:
import java.io.*;\n\npublic class MemMonitor {\n public static void main(String[] args) throws IOException {\n ProcessBuilder pb = new ProcessBuilder("free", "-m");\n pb.redirectErrorStream(true);\n Process process = pb.start();\n\n StringBuilder output = new StringBuilder();\n try (BufferedReader reader = new BufferedReader(\n new InputStreamReader(process.getInputStream()))) {\n String line;\n while ((line = reader.readLine()) != null) {\n output.append(line).append("\\n");\n }\n }\n\n int exitCode = process.waitFor();\n if (exitCode == 0) {\n System.out.println("मेमोरी (MB):");\n System.out.println(output.toString());\n } else {\n System.err.println("free कॉल करने में त्रुटि");\n }\n }\n}\n\nयह कोड Java में सिस्टम प्रोग्रामिंग का एक विशिष्ट उदाहरण है: नेटिव प्रोसेस चलाना, उसका आउटपुट पढ़ना, त्रुटियों को संभालना। महत्वपूर्ण: हमेशा redirectErrorStream(true) का उपयोग करें ताकि दो स्ट्रीम (stdout और stderr) को एक साथ पढ़ने पर deadlock न हो।
एनवायरनमेंट और वर्किंग डायरेक्टरी का प्रबंधन
\n\nProcessBuilder लॉन्च को बारीकी से कॉन्फ़िगर करने की अनुमति देता है। उदाहरण के लिए, विशिष्ट एनवायरनमेंट वेरिएबल्स के साथ स्क्रिप्ट चलाने के लिए:
\n\nProcessBuilder pb = new ProcessBuilder("python3", "backup.py");\npb.directory(ne