Masalah dengan Runtime.exec dan Android

Saya mengalami masalah saat menggunakan Runtime.exec dengan perangkat Android saya dan tidak tahu mengapa hal itu terjadi...

Berikut adalah contoh tes yang saya lakukan:

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Runtime runtime = Runtime.getRuntime();
        for(int i=0; i< 20; i++){
            Log.d("TESTEXEC", "EXEC N°"+i+" : BEGIN");
            try {
                Process process = runtime.exec("/system/bin/ps");
                process.getErrorStream().close();
                process.getOutputStream().close();
                process.getInputStream().close();
                process.waitFor();
            } catch (Throwable e) {
                e.printStackTrace();
            }
            Log.d("TESTEXEC", "EXEC N°"+i+" : END");
        }
    }
}

Jadi, pada dasarnya, ketika cuplikan ini berfungsi, ia akan mencetak ini:

EXEC N°0 : BEGIN
EXEC N°0 : END
EXEC N°1 : BEGIN
EXEC N°1 : END
...
EXEC N°19 : BEGIN
EXEC N°19 : END

Tapi alih-alih itu, kadang-kadang (sepertinya agak acak), malah hanya tercetak

EXEC N°0 : BEGIN

Dan semuanya terkunci... Semuanya sepertinya menabrak runtime.exec("..."), dan process.getErrorStream.close() tidak pernah dipanggil. Hal aneh lainnya : Bug selalu terjadi pada exec pertama.

Inilah yang saya dapatkan dengan DDMS : DDMS

Saya juga mengambil /data/anr/traces.txt, tapi itu tidak terlalu berguna :

----- pid 11489 at 2011-05-16 15:15:10 -----
Cmd line: com.testexec

DALVIK THREADS:
"main" prio=5 tid=1 NATIVE
  | group="main" sCount=1 dsCount=0 s=N obj=0x4001d8d0 self=0xcca0
  | sysTid=11489 nice=0 sched=0/0 cgrp=unknown handle=-1345021856
  at java.lang.ProcessManager.exec(Native Method)
  at java.lang.ProcessManager.exec(ProcessManager.java:224)
  at java.lang.Runtime.exec(Runtime.java:196)
  at java.lang.Runtime.exec(Runtime.java:285)
  at java.lang.Runtime.exec(Runtime.java:218)
  at com.testexec.MainActivity.onCreate(MainActivity.java:17)
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2629)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2681)
  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loop(Looper.java:123)
  at android.app.ActivityThread.main(ActivityThread.java:4641)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:521)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
  at dalvik.system.NativeStart.main(Native Method)

"java.lang.ProcessManager" daemon prio=5 tid=8 NATIVE
  | group="main" sCount=1 dsCount=0 s=N obj=0x460969f0 self=0x240f58
  | sysTid=11496 nice=0 sched=0/0 cgrp=unknown handle=2363544
  at java.lang.ProcessManager.watchChildren(Native Method)
  at java.lang.ProcessManager$1.run(ProcessManager.java:87)

"Binder Thread #2" prio=5 tid=7 NATIVE
  | group="main" sCount=1 dsCount=0 s=N obj=0x460895a0 self=0x1248e0
  | sysTid=11495 nice=0 sched=0/0 cgrp=unknown handle=1236304
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #1" prio=5 tid=6 NATIVE
  | group="main" sCount=1 dsCount=0 s=N obj=0x46086cf8 self=0x143480
  | sysTid=11494 nice=0 sched=0/0 cgrp=unknown handle=1324096
  at dalvik.system.NativeStart.run(Native Method)

"Compiler" daemon prio=5 tid=5 VMWAIT
  | group="system" sCount=1 dsCount=0 s=N obj=0x46084558 self=0x144560
  | sysTid=11493 nice=0 sched=0/0 cgrp=unknown handle=1153256
  at dalvik.system.NativeStart.run(Native Method)

"JDWP" daemon prio=5 tid=4 VMWAIT
  | group="system" sCount=1 dsCount=0 s=N obj=0x460842a0 self=0x12dc10
  | sysTid=11492 nice=0 sched=0/0 cgrp=unknown handle=1152968
  at dalvik.system.NativeStart.run(Native Method)

"Signal Catcher" daemon prio=5 tid=3 RUNNABLE
  | group="system" sCount=0 dsCount=0 s=N obj=0x460841e8 self=0x124d00
  | sysTid=11491 nice=0 sched=0/0 cgrp=unknown handle=1199296
  at dalvik.system.NativeStart.run(Native Method)

"HeapWorker" daemon prio=5 tid=2 VMWAIT
  | group="system" sCount=1 dsCount=0 s=N obj=0x441e2ee8 self=0x11fdd8
  | sysTid=11490 nice=0 sched=0/0 cgrp=unknown handle=1185776
  at dalvik.system.NativeStart.run(Native Method)

----- end 11489 -----

Saya agak putus asa saat ini, jadi jika ada yang punya ide, saya akan sangat menghargainya.


person Lyrkan    schedule 16.05.2011    source sumber
comment
Solusinya sederhana: jangan gunakan Runtime.exec(). Tidak ada program baris perintah yang merupakan bagian dari Android SDK. Program baris perintah apa pun yang ingin Anda gunakan harus ditulis ulang sebagai pustaka NDK dan dipanggil langsung dari aplikasi Java Anda melalui JNI.   -  person CommonsWare    schedule 16.05.2011
comment
Jadi saya harus menulis ulang seluruh perintah ps dengan NDK daripada hanya menggunakan 5 baris dengan Runtime.exec? :/   -  person Lyrkan    schedule 16.05.2011
comment
Anda memecahkan masalah apa pun yang Anda coba selesaikan menggunakan teknik yang akan bekerja di perangkat apa pun yang Anda coba terapkan. Jika ini hanya untuk ponsel Anda, dan Anda ingin menggunakan ps, silakan membenturkan kepala ke dinding agar dapat berfungsi. Jika Anda mencoba membuat aplikasi untuk Android Market atau distribusi luas serupa, jangan gunakan ps, melainkan implementasikan fungsionalitas yang Anda inginkan dengan cara lain, mungkin menggunakan NDK.   -  person CommonsWare    schedule 16.05.2011
comment
Fungsionalitas apa yang perlu Anda capai? 'ps' sebagian besar membaca dan menafsirkan informasi yang terdapat dalam direktori pid bernomor di bawah /proc   -  person Chris Stratton    schedule 16.05.2011
comment
Saya tidak berpikir untuk membaca langsung /proc/xxx/status. Saya hanya perlu mengambil PID dan nama proses saat ini.   -  person Lyrkan    schedule 16.05.2011


Jawaban (1)


Kemungkinan besar bug tersebut telah diperbaiki dalam komit Github ini. Intinya, ini menemui jalan buntu langsung setelah fork() tetapi sebelum melakukan exec() yang sebenarnya karena seseorang mencoba malloc.

person dascandy    schedule 14.02.2012