JShell Java 9 में पेश किया गया एक इंटरैक्टिव REPL (Read-Eval-Print Loop) टूल है जो कमांड-लाइन पर Java कोड स्निपेट्स को तुरंत 실행 और परीक्षण करने की अनुमति देता है। Java 9 ने Process API को महत्वपूर्ण रूप से बेहतर किया, जिसमें ProcessHandle और ProcessHandle.Info इंटरफेस पेश किए गए जो ऑपरेटिंग सिस्टम प्रक्रियाओं को प्रबंधित और नियंत्रित करने के लिए हैं।
मुख्य इंटरफेस
- ProcessHandle: एक देशी प्रक्रिया की पहचान करता है और उस पर नियंत्रण प्रदान करता है - जीवंतता (liveness) जांचना, बच्चे सूचीबद्ध करना, जानकारी प्राप्त करना, या प्रक्रिया को नष्ट करना।
- ProcessHandle.Info: एक प्रक्रिया का जानकारी स्नैपशॉट प्रदान करता है - उपयोगकर्ता, कमांड, प्रारंभ समय, कुल CPU समय, आर्गुमेंट्स आदि।
JShell सत्र उदाहरण
jshell> ProcessHandle currentProcess = ProcessHandle.current()
currentProcess ==> 12345
jshell> System.out.println("Current Process ID: " + currentProcess.pid())
Current Process ID: 12345
jshell> currentProcess.info()
$3 ==> Optional[user=Optional[username], cmd=/usr/lib/jvm/java-17/bin/java, startInstant=Optional[2024-01-15T10:30:00Z], totalDuration=Optional[PT5.123S], arguments=Optional[[...]]]
jshell> // PID द्वारा प्रक्रिया प्राप्त करें
jshell> ProcessHandle.of(12345)
$5 ==> Optional[12345]
jshell> // बच्चे प्रक्रियाएं सूचीबद्ध करें
jshell> Stream children = ProcessHandle.current().children()
children ==> java.util.stream.ReferencePipeline$Head@...
jshell> children.count()
$7 ==> 2
jshell> // बच्चे प्रक्रियाओं को नष्ट करें (सावधानी से उपयोग करें!)
jshell> children.forEach(ph -> System.out.println(ph.destroy() ? "Terminated " + ph.pid() : "Failed to terminate " + ph.pid()))
Terminated 12346
Terminated 12347
महत्वपूर्ण नोट्स
java.lang.IllegalStateException: stream has already been operated upon or closed। ऐसा इसलिए हुआ क्योंकि children.count() एक टर्मिनल ऑपरेशन है जो स्ट्रीम को बंद कर देता है। बाद के forEach के लिए एक नई स्ट्रीम की आवश्यकता होती है।
सही पैटर्न
// सही: प्रत्येक ऑपरेशन के लिए नई स्ट्रीम प्राप्त करें
ProcessHandle.current().children().forEach(ph -> {
boolean destroyed = ph.destroy(); // विनम्र समाप्ति
// या ph.destroyForcibly() बलपूर्वक समाप्ति के लिए
System.out.println(destroyed ? "Terminated: " + ph.pid() : "Failed: " + ph.pid());
});
// या सूची में संग्रहीत करें
List childList = ProcessHandle.current().children().collect(Collectors.toList());
childList.forEach(ph -> ph.destroy());
व्यावहारिक उपयोग केस
import java.lang.ProcessHandle;
import java.util.stream.Collectors;
public class ProcessManager {
public static void printProcessTree() {
ProcessHandle current = ProcessHandle.current();
System.out.println("=== प्रक्रिया पेड़ ===");
System.out.println("PID: " + current.pid());
current.info().ifPresent(info -> {
info.command().ifPresent(cmd -> System.out.println("कमांड: " + cmd));
info.user().ifPresent(user -> System.out.println("उपयोगकर्ता: " + user));
info.startInstant().ifPresent(start -> System.out.println("प्रारंभ: " + start));
info.totalDuration().ifPresent(dur -> System.out.println("CPU समय: " + dur));
});
System.out.println("\nबच्चे प्रक्रियाएं:");
current.children()
.forEach(child -> printProcessInfo(child, " "));
}
private static void printProcessInfo(ProcessHandle ph, String indent) {
System.out.println(indent + "PID: " + ph.pid());
ph.info().ifPresent(info -> {
info.command().ifPresent(cmd -> System.out.println(indent + "कमांड: " + cmd));
info.user().ifPresent(user -> System.out.println(indent + "उपयोगकर्ता: " + user));
});
// पुनरावर्ती रूप से पोते प्रिंट करें
ph.children().forEach(grandChild -> printProcessInfo(grandChild, indent + " "));
}
}
सारांश
| मेट्रिक | मेथड | विवरण |
|---|---|---|
| PID | process.pid() | प्रक्रिया पहचानकर्ता लौटाता है |
| जानकारी | process.info() | ProcessHandle.Info स्नैपशॉट लौटाता है |
| बच्चे | process.children() | बच्चे प्रक्रियाओं की स्ट्रीम लौटाता है |
| सभी वंशज | process.descendants() | सभी वंशज प्रक्रियाओं की स्ट्रीम लौटाता है |
| विनम्र समाप्ति | process.destroy() | SIGTERM भेजता है, boolean लौटाता है |
| बलपूर्वक समाप्ति | process.destroyForcibly() | SIGKILL भेजता है, boolean लौटाता है |
| जीवंतता | process.isAlive() | जांचता है कि प्रक्रिया चल रही है या नहीं |