CodeGym /Kurslar /JAVA 25 SELF /Proseslərlə işləyərkən tipik səhvlərin təhlili

Proseslərlə işləyərkən tipik səhvlərin təhlili

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

1. Axınların oxunması/yazılması zamanı deadlock

Ən xoşagəlməz səhvlərdən biri — proses ilişib tamamlanmır, halbuki hər şey düzgün edilib kimi görünür. Tez‑tez səbəb — çıxış buferinin dolması və ya xarici prosesin səhvləridir. Hər iki axın (stdout və stderr) oxunmasa, proses nəsə çıxarmağa çalışarkən “kilidlənə” bilər, çünki onun buferindən məlumatı götürən yoxdur.

Problem nümunəsi

ProcessBuilder builder = new ProcessBuilder("java", "-version");
Process process = builder.start();
// Yalnız stdout-u oxuyuruq, stderr-i isə yox sayırıq!
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}
process.waitFor();

Əgər əmr nəyisə stderr-ə yazırsa (məsələn, java -version demək olar ki, həmişə ora yazır!), bu axın dolur və proses ilişir.

Necə düzgün

Hər iki axını paralel oxuyun (ayrı thread-lər və ya ExecutorService vasitəsilə):

ProcessBuilder builder = new ProcessBuilder("java", "-version");
Process process = builder.start();

// stdout-u oxuyuruq
Thread stdoutThread = new Thread(() -> {
    try (BufferedReader reader = new BufferedReader(
            new InputStreamReader(process.getInputStream()))) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println("[stdout] " + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
});

// stderr-i oxuyuruq
Thread stderrThread = new Thread(() -> {
    try (BufferedReader reader = new BufferedReader(
            new InputStreamReader(process.getErrorStream()))) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.err.println("[stderr] " + line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
});

stdoutThread.start();
stderrThread.start();

process.waitFor();
stdoutThread.join();
stderrThread.join();

Nəticə:
Əgər stderr oxunmasa — proses ilişə bilər.
Əgər stdout oxunmasa — o da ilişə bilər.
Hər iki axını oxuyun — və rahat olun!

2. Kodlaşdırma problemləri

Xarici proseslər mətni sizin Java proqramınızın susmaya görə istifadə etdiyindən fərqli kodlaşdırma ilə yaza bilər. Lazımi kodlaşdırmanı göstərməsəniz, mətn əvəzinə anlaşılmaz simvollar görəcəksiniz (xüsusilə kiril yazısında nəzərə çarpır).

Səhv nümunəsi

BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

Bu kod sistemin susmaya görə kodlaşdırmasından istifadə edir. Lakin əgər xarici proses, məsələn, UTF-8 ilə yazırsa, sizdə isə Windows-1251-dirsə, kiril mətnləri anlaşılmaz simvollara çevriləcək.

Necə düzgün

Lazım olan kodlaşdırmanı bilirsinizsə, onu açıq şəkildə verin:

BufferedReader reader = new BufferedReader(
    new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8)
);

Əmin deyilsinizsə — proqramın sənədlərini oxuyun və ya bir neçə variantı yoxlayın.

Faydalı məsləhət: Windows-da konsol utilitləri tez-tez CP866 və ya Windows-1251 istifadə edir, Linux-da isə — UTF-8.

3. Platforma fərqləri

Bir OS-də işləyən komandalar digərində olmaya bilər. Məsələn, ls Linux/Mac-də var, amma Windows-da yoxdur (orada — dir). Komandaların sintaksisi, yol ayrıcıları və dırnaqlar fərqlənir.

Səhv nümunəsi

ProcessBuilder builder = new ProcessBuilder("ls", "-l");
builder.start(); // Windows-da: "ls" tapılmadı!

Necə düzgün

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

Fayl yolu: “/” və ya “\” əvəzinə File.separator istifadə edin ki, yollarla bağlı problem yaşamayasınız.

4. Giriş hüquqları problemləri

Bəzi komandalar administrator səlahiyyətləri tələb edir (sistem fayllarının silinməsi, şəbəkə sazlamalarının dəyişdirilməsi və s.). Hüquqlar kifayət etmədikdə, əmr səhvlə tamamlanacaq və ya ümumiyyətlə işə düşməyəcək.

Nümunə

ProcessBuilder builder = new ProcessBuilder("rm", "-rf", "/root/secret.txt");
Process process = builder.start();
// ... 'Permission denied' xətasını gözləyirik

Necə düzgün

  • Əmriniz üçün yüksəldilmiş hüquqların tələb olunub-olunmadığını yoxlayın.
  • Prosesin qaytarma kodunu process.exitValue() vasitəsilə emal edin.
  • stderr-i oxuyun — səbəb çox vaxt orada olur (məsələn, “Permission denied”).

5. Resurs sızmaları

Prosesin axınları (InputStream, OutputStream, ErrorStream) bağlanmasa, onlar “asılı” qala, resursları tuta və hətta tamamlanmanı bloklaya bilər. Eynilə, prosesi dayandırmasanız, o, sistemdə “zombi”yə çevrilə bilər.

Səhv nümunəsi

Process process = builder.start();
// ... işləyirik, amma axınları bağlamırıq!

Necə düzgün

Axınlar üçün try-with-resources istifadə edin:

try (BufferedReader reader = new BufferedReader(
         new InputStreamReader(process.getInputStream()))) {
    // Çıxışı oxuyuruq
}

Proseslə iş bitdikdən sonra onu düzgün dayandırın:

process.destroy(); // Prosesi bitirmək (əgər hələ işləyirsə)

Diqqət: axınlar bağlanmasa — yaddaş sızmaları, ilişmələr və sistem problemləri mümkündür (xüsusən proseslər kütləvi işə salınanda).

6. İnteraktiv qarşılıqlı əlaqədə deadlock

İnteraktiv mübadilə zamanı qarşılıqlı bloklanmaya düşmək asandır: Java cavabı gözləyir, xarici proses isə sizin məlumatlarınızı. Nəticədə hər ikisi “susur”. Və ya siz mesaj göndərmisiniz, amma cavabı oxumursunuz — müəyyən anda xarici proqramın buferi dolur və o, yazmanı dayandırır.

Bunun qarşısını almaq üçün vəzifələri ayırın: bir thread oxumağa, digəri isə yazmağa cavabdeh olsun. Beləliklə, qarşılıqlı əlaqə paralel gedir və heç kim heç kimi gözlətmir. Həmçinin iş bitdikdən sonra açıq axınları saxlamayın — sistemi artıq resursları tutmaqdan yayındırmaq üçün onları bağlayın.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Qorunan zonaya daxil olma 🚫
Qorunan zonaya daxil olma 🚫
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Detektivin Hərşeyi Görən Gözü 🕵️
Detektivin Hərşeyi Görən Gözü 🕵️
1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Proseslərlə iş
Proseslərlə iş
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION