ปัญหากับ Runtime.exec และ Android

ฉันมีปัญหาเมื่อฉันใช้ Runtime.exec กับอุปกรณ์ Android ของฉัน และไม่รู้ว่าทำไมมันจึงเกิดขึ้น...

นี่คือตัวอย่างการทดสอบที่ฉันทำ:

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");
        }
    }
}

โดยพื้นฐานแล้ว เมื่อตัวอย่างนี้ใช้งานได้ มันจะพิมพ์สิ่งนี้:

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

แต่แทนที่จะเป็นอย่างนั้น บางครั้ง (ดูเหมือนว่ามันจะสุ่มไปหน่อย) มันก็แค่พิมพ์ออกมา

EXEC N°0 : BEGIN

และทุกอย่างล็อค... ดูเหมือนว่าทุกสิ่งจะผิดพลาดใน runtime.exec("...") และไม่เคยมีการเรียก process.getErrorStream.close() สิ่งที่แปลกอีกอย่าง: บั๊กมักเกิดขึ้นในผู้บริหารคนแรกเสมอ

นี่คือสิ่งที่ฉันได้รับจาก DDMS : DDMS

ฉันยังดึงข้อมูล /data/anr/traces.txt ด้วย แต่มันไม่มีประโยชน์จริงๆ :

----- 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 -----

ตอนนี้ฉันค่อนข้างสิ้นหวัง ดังนั้นถ้าใครมีความคิด ฉันจะขอบคุณมาก


person Lyrkan    schedule 16.05.2011    source แหล่งที่มา
comment
วิธีแก้ปัญหานั้นง่ายมาก: อย่าใช้ Runtime.exec() ไม่มีโปรแกรมบรรทัดคำสั่งที่เป็นส่วนหนึ่งของ Android SDK โปรแกรมบรรทัดคำสั่งใดๆ ที่คุณต้องการใช้ควรเขียนใหม่เป็นไลบรารี NDK และเรียกใช้โดยตรงจากแอป Java ของคุณผ่าน JNI   -  person CommonsWare    schedule 16.05.2011
comment
ดังนั้นฉันควรเขียนคำสั่ง ps ใหม่ทั้งหมดด้วย NDK แทนที่จะใช้เพียง 5 บรรทัดกับ Runtime.exec ? :/   -  person Lyrkan    schedule 16.05.2011
comment
คุณแก้ไขปัญหาใดก็ตามที่คุณพยายามแก้ไขโดยใช้เทคนิคที่จะทำงานได้กับอุปกรณ์ใดก็ตามที่คุณพยายามปรับใช้ หากนี่เป็นเพียงโทรศัพท์ของคุณ และคุณต้องการใช้ ps คุณสามารถเอาหัวโขกกำแพงเพื่อให้มันใช้งานได้ หากคุณกำลังพยายามสร้างแอปพลิเคชันสำหรับ Android Market หรือการเผยแพร่ในวงกว้างที่คล้ายกัน อย่าใช้ ps แต่ควรใช้ฟังก์ชันที่คุณต้องการในลักษณะอื่น ซึ่งอาจใช้ NDK   -  person CommonsWare    schedule 16.05.2011
comment
ฟังก์ชันการทำงานที่คุณต้องการคืออะไร? 'ps' ส่วนใหญ่จะอ่านและตีความข้อมูลที่อยู่ในไดเร็กทอรี pid ที่มีหมายเลขกำกับภายใต้ /proc   -  person Chris Stratton    schedule 16.05.2011
comment
ฉันไม่ได้คิดที่จะอ่านโดยตรง /proc/xxx/status ฉันแค่ต้องดึงข้อมูล PID และชื่อของกระบวนการปัจจุบัน   -  person Lyrkan    schedule 16.05.2011


คำตอบ (1)


เป็นไปได้มากว่าข้อบกพร่องที่ได้รับการแก้ไขใน คอมมิต Github นี้ โดยพื้นฐานแล้ว มันจะหยุดชะงักโดยตรงหลังจาก fork() แต่ก่อนที่จะดำเนินการจริง exec() เนื่องจากมีคนพยายาม malloc

person dascandy    schedule 14.02.2012