CodeGym /Kurslar /JAVA 25 SELF /ProcessBuilder — xarici proseslərin işə salınması

ProcessBuilder — xarici proseslərin işə salınması

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

1. OS-də proseslər nədir və onları Java-dan niyə işə salmaq lazımdır

Proseslər: JVM-dən bash-a və geri

Kompüteri işə salıb brauzer, messencer və ya oyunu açanda — bunların hər biri ayrıca prosesdir. Əməliyyat sistemi hər proqram üçün ayrıca bir «mini‑aləm» yaradır: yaddaş ayırır, prosessor vaxtı verir, fayllar və şəbəkə ilə işləməyə icazə verir. Beləcə proqramlar yanaşı yaşayır, bir‑birinə mane olmur.

Java proqramı da istisna deyil. java MyApp işə salanda sistem onun üçün bütün lazım olan resurslarla ayrıca proses yaradır. Artıq onun daxilində sizin proqramınız işləyir: hesablayır, çəkir, faylları oxuyur — nə lazımdırsa onu edir.

Amma bəzən təkcə Java kifayət etmir. Bəzən başqa proqramdan kömək istəmək lazım olur — faylları qablaşdırmaq üçün arxivləşdiricini işə salmaq, videonu emal etmək üçün ffmpeg çağırmaq və ya sadəcə kompüterdə hansı Java versiyasının quraşdırıldığını öyrənmək. Bu, xarici prosesi işə salmaqdır: Java sistemə «bu utiliti çağır» deyir və sonra onun işinin nəticəsini alır.

Əslində bu, proqramı daha çevik etmək üsuludur: müxtəlif alətləri birləşdirmək, rutini avtomatlaşdırmaq və ya məntiqinizi mövcud sistem proseslərinə inteqrasiya etmək. Bəzən işi sıfırdan yazmaqdan isə xarici əmrdən xahiş edib bir hissəsini etdirmək daha rahatdır.

JVM vs. xarici proses

JVM prosesi — Java virtual maşınında icra olunan sizin proqramınızdır.

Xarici proses — istənilən başqa proqram: kalkulyator, Python skripti, komanda sətri, hətta başqa bir Java nümunəsi.

2. ProcessBuilder sinfi

«Qədim» zamanlarda Java prosesləri Runtime.getRuntime().exec() metodu ilə işə salırdı. Bu, ən rahat və təhlükəsiz üsul deyildi — mikroskopla mıx vurmağa cəhd kimi. Buna görə də Java 5-dən etibarən ProcessBuilder sinfi yarandı; o, xarici prosesləri daha çevik və anlaşılan şəkildə yaratmağa, tənzimləməyə və işə salmağa imkan verir.

ProcessBuilder — sanki bir «konstruktor»dur: gələcək proses üçün öncədən bütün parametrləri təyin etməyə imkan verir — əmr, arqumentlər, işçi qovluq, mühit dəyişənləri və s.

Sintaksis: prosesin yaradılması

ProcessBuilder pb = new ProcessBuilder("əmr", "arqument1", "arqument2", ...);
  • Birinci arqument — əmr adıdır (məsələn, "ls", "dir", "ping", "java").
  • Qalanları — əmrin parametrləridir.

Nümunə: ls (Linux/Mac) və ya dir (Windows) əmrlərinin işə salınması

ProcessBuilder pb;
if (System.getProperty("os.name").toLowerCase().contains("win")) {
    pb = new ProcessBuilder("cmd.exe", "/c", "dir");
} else {
    pb = new ProcessBuilder("ls", "-l");
}

Yeri gəlmişkən, Windows-da dir, copy və s. kimi əmrlər ayrıca icra olunan fayllar deyil, komanda sətrinin (cmd.exe) «daxili» əmrləridir. Buna görə də onları cmd.exe /c ... vasitəsilə işə salmaq lazımdır.

Nümunə: sadə prosesin işə salınması

ProcessBuilder pb = new ProcessBuilder("echo", "Hello, Java!");

3. Proses mühitinin tənzimlənməsi

Arqumentlərin ötürülməsi. Əmr arqumentləri ayrı-ayrı sətirlər kimi verilir:

ProcessBuilder pb = new ProcessBuilder("ping", "google.com");

İşçi qovluğun göstərilməsi. Susmaya görə proses sizin proqramınızla eyni qovluqda işə salınır. Amma başqa bir qovluğu açıq şəkildə göstərmək olar:

pb.directory(new java.io.File("/tmp"));      // Linux/Mac üçün
pb.directory(new java.io.File("C:\\Temp"));  // Windows üçün

Mühit dəyişənlərinin dəyişdirilməsi. Hər prosesin öz mühit dəyişənləri (environment variables) var. Onları əlavə etmək və ya dəyişmək olar:

pb.environment().put("MY_VAR", "HelloFromJava");

Bu, xarici proses hansısa spesifik dəyişənləri gözləyirsə, faydalı ola bilər.

4. Prosesin işə salınması

Metod start(). Hər şeyi tənzimlədikdən sonra prosesi işə salmaq vaxtıdır:

Process process = pb.start();

start() metodu Process obyektini qaytarır; o, işə salınmış proqramı idarə etməyə imkan verir: onun çıxışını oxumaq, girişinə yazmaq, onu tamamlandırmaq və s.

İstisnaların emalı. Əgər əmr tapılmadısa, icazələr yoxdursa və ya işə salma zamanı başqa bir xəta baş verərsə, start() IOException ata bilər.

Nümunə:

try {
    Process process = pb.start();
    // Proseslə işləyirik...
} catch (IOException e) {
    System.out.println("Prosesin işə salınması xətası: " + e.getMessage());
}

5. Təcrübə: Sadə əmrlərin işə salınması

Nümunə 1: Qovluqdakı faylların siyahısını çıxarmaq

import java.io.*;

public class ProcessDemo {
    public static void main(String[] args) {
        // OS-ə uyğun əmri təyin edirik
        ProcessBuilder pb;
        if (System.getProperty("os.name").toLowerCase().contains("win")) {
            pb = new ProcessBuilder("cmd.exe", "/c", "dir");
        } else {
            pb = new ProcessBuilder("ls", "-l");
        }

        try {
            Process process = pb.start();

            // Prosesin çıxışını (stdout) oxuyuruq
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream())
            );
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            // Prosesin başa çatmasını gözləyirik
            int exitCode = process.waitFor();
            System.out.println("Proses bu kodla başa çatdı: " + exitCode);

        } catch (IOException | InterruptedException e) {
            System.out.println("Xəta: " + e.getMessage());
        }
    }
}

Burada nə baş verir?

  • OS-in hansı olduğunu müəyyən edib uyğun əmri seçirik.
  • ProcessBuilder obyektini lazım olan əmrlə yaradırıq.
  • Prosesi start() ilə işə salırıq.
  • Prosesin stdout-dan sətirləri oxuyub ekrana çıxarırıq.
  • Prosesin başa çatmasını gözləyirik (waitFor()).
  • Çıxış kodunu göstəririk (0 — uğur, digər dəyərlər — xəta).

Nümunə 2: java -version işə salınması

ProcessBuilder pb = new ProcessBuilder("java", "-version");
try {
    Process process = pb.start();

    // java -version məlumatı stderr-ə yazır, buna görə getErrorStream() oxuyuruq
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getErrorStream())
    );
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
    process.waitFor();
} catch (IOException | InterruptedException e) {
    e.printStackTrace();
}

Vacib nüans: Bəzi əmrlər (məsələn, java -version) məlumatı standart çıxışa (stdout) deyil, xəta axınına (stderr) yazır. Buna görə bəzən process.getErrorStream() oxumaq lazımdır.

6. Kross‑platformalıq: Windows və Linux/Mac arasındakı fərqlər

  • Əmrlər və onların parametrləri fərqli ola bilər.
  • Fayl yolları fərqli yazılır (C:\Temp/tmp).
  • Bəzi əmrlər (məsələn, ls, cat) yalnız Unix‑tipli sistemlərdə var, Windows-da onları analoglar əvəz edir (dir, type).
  • Windows-da daxili əmrlər yalnız cmd.exe /c əmri vasitəsilə işə salınır.

OS yoxlanışı nümunəsi:

String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
    // Windows
} else if (os.contains("mac")) {
    // macOS
} else if (os.contains("nix") || os.contains("nux")) {
    // Linux
}

Məsləhət: Əgər kross‑platformalığa güvənirsinizsə, proqramlarınızı hədəf OS-lərdə mütləq test edin.

7. Cədvəl: ProcessBuilder-in əsas metod və imkanları

Metod/sahə Təyinat İstifadə nümunəsi
new ProcessBuilder(String...)
Komanda və arqumentlərlə proses yaratmaq
new ProcessBuilder("ls", "-l")
.directory(File)
İşçi qovluğu təyin etmək
.directory(new File("/tmp"))
.environment()
Mühit dəyişənlərini əldə etmək/dəyişmək
.environment().put("VAR", "value")
.start()
Prosesi işə salmaq
Process p = pb.start()
Process.getInputStream()
Prosesin stdout-unu əldə etmək
InputStream
Process.getErrorStream()
Prosesin stderr-ni əldə etmək
InputStream
Process.getOutputStream()
Prosesin stdin-ni əldə etmək
OutputStream
Process.waitFor()
Prosesin başa çatmasını gözləmək
int code = p.waitFor()
Process.exitValue()
Prosesin çıxış kodunu almaq
int code = p.exitValue()

8. Xarici prosesləri işə salarkən tipik səhvlər

Səhv №1: Əmr tapılmadı. Əmr adında səhv etmisinizsə və ya o sistemdə yoxdursa, IOException alacaqsınız: Cannot run program .... Məsələn, Windows-da ls işə salmaq cəhdi.

Səhv №2: Arqumentlərin yanlış ötürülməsi. Bütün əmri bir sətirdə birləşdirməyin! Düzgün: new ProcessBuilder("ping", "google.com"). Yanlış: new ProcessBuilder("ping google.com").

Səhv №3: OS fərqləri nəzərə alınmayıb. Linux-da əla işləyən əmr Windows-da mövcud olmaya bilər və əksinə. Həmişə OS-i yoxlayın və əmri uyğunlaşdırın.

Səhv №4: Prosesin çıxışı oxunmayıb. Prosesin çıxışını oxumasanız, buffer dolduğu üçün «asılı» qala bilər. Hətta çıxışdan istifadə etməyəcəyiniz halda belə — onu oxuyun və məsələn, sadəcə gözardı edin.

Səhv №5: Axınlar bağlanmayıb. Resurs sızmalarının qarşısını almaq üçün prosesin axınlarını istifadə etdikdən sonra bağlamaq lazımdır.

Səhv №6: İstisnalar emal olunmayıb. Xarici prosesi işə salmaq risklidir. Həmişə try-catch istifadə edin və istifadəçini xətalar barədə məlumatlandırın.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION