Process API (Süreç Yönetimi)
Bazen Java programının dışındaki programları çalıştırman gerekir: bir sistem komutu, başka bir betik, harici bir araç. Veya çalışan süreçler hakkında bilgi almak istersin (PID, başlangıç zamanı, ebeveyn). Java'nın Pro…
Process API (Süreç Yönetimi)
Bazen Java programının dışındaki programları çalıştırman gerekir: bir sistem komutu, başka bir
betik, harici bir araç. Veya çalışan süreçler hakkında bilgi almak istersin (PID, başlangıç zamanı,
ebeveyn). Java'nın Process API'si bunları sağlar: komut çalıştırmak için ProcessBuilder,
süreçleri incelemek/yönetmek için ProcessHandle (Java 9+).
ProcessHandle: süreçleri incelemek (Java 9)
ProcessHandle, yeni bir süreç başlatmadan, çalışan süreçler hakkında bilgi verir:
ProcessHandle benim = ProcessHandle.current(); // bu JVM süreci benim.pid(); // işletim sistemi PID'i benim.info().command(); benim.info().startInstant(); benim.info().user(); benim.parent(); benim.children(); benim.isAlive(); benim.destroy(); ProcessHandle.allProcesses(); // sistemdeki tüm süreçler (akış)
Örnek 1 (./Ornek1.java) bu JVM sürecinin PID'ini, bilgilerini ve ebeveynini gösterir. (Hangi
bilgilerin dolu geleceği işletim sistemine göre değişir.) İzleme, yönetim panelleri ve süreç
ağaçlarını incelemek için kullanılır.
ProcessBuilder: dış komut çalıştırmak
ProcessBuilder, dış bir program/komut çalıştırmanın modern yoludur (eski Runtime.exec'in
halefi):
ProcessBuilder pb = new ProcessBuilder("/bin/echo", "merhaba"); pb.redirectErrorStream(true); // stderr -> stdout Process p = pb.start(); // p.getInputStream() ile çıktıyı oku... int kod = p.waitFor(); // bitmesini bekle + çıkış kodu
Önemli metotlar:
command(...): Komut ve argümanları (her argüman ayrı verilir).start(): Süreci başlatır, birProcessdöndürür.getInputStream/getOutputStream/getErrorStream: Süreçle veri alışverişi.redirectErrorStream(true): Hata akışını çıktıyla birleştirir.directory(file)/environment(): Çalışma dizini ve ortam değişkenleri.waitFor(): Sürecin bitmesini bekler, çıkış kodunu (0 = başarılı) döndürür.
Örnek 2 (./Ornek2.java) bir echo komutunu çalıştırıp çıktısını okur ve çıkış kodunu alır.
Çıktı akışlarını yönetmek (deadlock tuzağı)
Bir sürecin çıktısını okumadan büyük veri üretmesini beklersen, sürecin çıktı tamponu dolar ve kilitlenme (deadlock) olabilir. Bu yüzden:
- Çıktı/hata akışlarını okumalısın (veya
redirect...ile yönlendirmelisin). - Büyük çıktılarda akışları ayrı thread'lerde oku, ya da
redirectOutput/redirectErrorile dosyaya/PIPE'a yönlendir.
Güvenlik: komut enjeksiyonu
Komutu asla kullanıcı girdisinden string birleştirerek kurma ("rm " + kullaniciGirdisi
gibi) — komut enjeksiyonu açığıdır. Argümanları ProcessBuilder'a ayrı ayrı ver; kabuk (shell)
yorumlamasından kaçın. Mümkünse beyaz liste (whitelist) ile sınırla.
Özet
Java'nın Process API'sini öğrendik: çalışan süreçleri başlatmadan inceleyen ProcessHandle
(PID, info, parent; Örnek 1) ve dış komut çalıştıran ProcessBuilder (start, akışlar, waitFor;
Örnek 2); çıktı akışı deadlock tuzağına ve komut enjeksiyonu güvenliğine değindik. Sırada, ikili
veriyi metne çevirme standardı: Base64.
▶ Kod Örnekleri(2)
Ornek1
çalıştırılabilir1// Ornek1: ProcessHandle (Java 9) — çalışan süreçler hakkında bilgi (yeni süreç başlatmadan).
2// Çalıştırma: java Ornek1.java
3public class Ornek1 {
4
5 public static void main(String[] args) {
6 // Şu anki JVM sürecinin tanıtıcısı:
7 ProcessHandle benim = ProcessHandle.current();
8 System.out.println("Bu sürecin PID'i: " + benim.pid());
9
10 // Süreç bilgileri (info): komut, başlangıç zamanı, kullanıcı... (platforma göre dolu/boş olabilir)
11 ProcessHandle.Info bilgi = benim.info();
12 System.out.println("Komut : " + bilgi.command().orElse("(bilinmiyor)"));
13 System.out.println("Başlangıç: " + bilgi.startInstant().map(Object::toString).orElse("(bilinmiyor)"));
14 System.out.println("Kullanıcı: " + bilgi.user().orElse("(bilinmiyor)"));
15
16 // Ebeveyn süreç (varsa):
17 benim.parent().ifPresentOrElse(
18 p -> System.out.println("Ebeveyn PID: " + p.pid()),
19 () -> System.out.println("Ebeveyn süreç bilgisi yok"));
20
21 // Süreç canlı mı?
22 System.out.println("Süreç canlı mı? " + benim.isAlive());
23
24 System.out.println("""
25
26 --- ProcessHandle (Java 9) ---
27 Çalışan SÜREÇLER hakkında bilgi verir (yeni süreç BAŞLATMADAN):
28 pid(), info() (komut/başlangıç/kullanıcı), parent(), children(), isAlive(), destroy().
29 ProcessHandle.current(): bu JVM süreci. ProcessHandle.allProcesses(): sistemdeki süreçler.
30 İzleme, yönetim ve süreç ağaçlarını incelemek için kullanılır (bilgiler platforma göre değişir).""");
31 }
32}Ornek2
çalıştırılabilir1// Ornek2: ProcessBuilder — bir dış komut çalıştırıp çıktısını okumak.
2// Çalıştırma: java Ornek2.java
3import java.io.BufferedReader;
4import java.io.InputStreamReader;
5
6public class Ornek2 {
7
8 public static void main(String[] args) throws Exception {
9 // ProcessBuilder ile dış bir komut çalıştır. (Burada taşınabilir, zararsız bir komut.)
10 // Unix'te /bin/echo; çıktıyı ve hata akışını birleştir.
11 ProcessBuilder pb = new ProcessBuilder("/bin/echo", "Merhaba ProcessBuilder!");
12 pb.redirectErrorStream(true); // stderr -> stdout (tek akışta oku)
13
14 System.out.println("Komut çalıştırılıyor: " + pb.command());
15 Process surec = pb.start();
16
17 // Sürecin çıktısını oku:
18 try (BufferedReader r = new BufferedReader(new InputStreamReader(surec.getInputStream()))) {
19 String satir;
20 while ((satir = r.readLine()) != null) {
21 System.out.println(" çıktı: " + satir);
22 }
23 }
24
25 // Bitmesini bekle ve çıkış kodunu al:
26 int kod = surec.waitFor();
27 System.out.println("Çıkış kodu: " + kod + " (0 = başarılı)");
28
29 System.out.println("""
30
31 --- ProcessBuilder ---
32 Dış programları/komutları Java'dan çalıştırmanın yoludur (eski Runtime.exec'in halefi).
33 Akış: new ProcessBuilder(komut, arg...).start() -> Process.
34 getInputStream/getOutputStream/getErrorStream ile süreçle veri alışverişi.
35 redirectErrorStream(true): hata akışını çıktıyla birleştirir. waitFor(): bitmesini bekle + çıkış kodu.
36 directory()/environment() ile çalışma dizini ve ortam değişkenleri ayarlanır.
37 GÜVENLİK: komutu kullanıcı girdisinden kurma (komut enjeksiyonu); argümanları ayrı ayrı ver.""");
38 }
39}