[Java] [Android] [Process] The service of violence can solve all, violent ways to execute command line statements

Source: Internet
Author: User
Tags close close getmessage

Whether you are executing a command-line statement in Java or Android, the same way you create a child process executes the call executable command, similar to cmd in Windows.

At this point you have two ways to do it: Processbuilder and runtime; two ways to create them are different, as for the difference: [Java][android][process] Processbuilder and runtime

There are certain limitations when creating a sub-Process execution command in Android:

The 1.JVM provides limited memory.

2. There is a limited size between the underlying buffers.

3. Congestion is easily caused by high concurrency.

Based on the previous points, we have to be cautious when executing the command line, and cannot be created casually.

In the previous article, I mentioned: [java][android][process] Process creation + CONTROL + analysis experience on some of my management methods have been the implementation of the analysis; it boils down to the following: When creating a child process, you create a thread to read the output stream information, Exit on time after return;



through the above control method can effectively solve the bottom Processmanager Thread Dead condition (Waiting for IO buffer condition), the child process will go into wait and never quit when this thread dies. This situation can be achieved by executing tens of thousands of commands without problems. But after half a month of observation I found that it is not the most stable way, when there are many other IO operations such as (file read/write, network request, etc.) appear, I executed to close to 20,000 command line after the same problem.

after the query, although we started the thread to read the excess stream data, but when the thread is many or requests a lot of time the thread may not be able to start immediately, and when the IO is full, then will enter the IO critical section wait, that is, the thread is actually not omnipotent. Fortunately, there is a mechanism in Android: Services .

What is Android service? I do not say Baidu a little bit to know!

Now, let's talk about my new ideas:

First we create a service and set up a Service as a standalone process: android:process= ". Command.commandservice"

Then we put the implementation part in the service we open, use a class to control the service start and invoke the service to do the task, its task is to put the above part in the Service control implementation,


Does that look like it's no different? In fact, the difference has come, the first because it is the service of the independent process, so there will be a separate JVM space , while the process of IO and the main thread io is not the same (logically), so if the operation of other streams in the main process does not affect the flow of the independent process.

And there is a particularly important situation: when the stand-alone service process has a dead (IO) Wait, the daemon in the service will automatically kill itself , and then wait for the restart to resume the task.


Implementation code:

Public Commandserviceimpl () {//thread-initialization of threads = new Thread (CommandServiceImpl.class.getName ()) { @Override public void Run () {while (thread = = This &&!this.isinterr                            Upted ()) {if (commandexecutors! = null && commandexecutors.size () > 0) {                            Lock.lock ();                            Logutil.i (TAG, "executors Size:" + commandexecutors.size ());                                    for (Commandexecutor executor:commandexecutors) {if (Executor.istimeout ())                                    try {killself ();                                    } catch (RemoteException e) {e.printstacktrace ();                                    if (thread! = this && this.isinterrupted ())      Break                      } lock.unlock ();                        } try {Thread.Sleep (10000);                        } catch (Interruptedexception e) {e.printstacktrace ();            }                    }                }            };            Thread.setdaemon (TRUE);        Thread.Start (); }

<span style= "White-space:pre" ></span>/**         * Kill yourself         *         * @throws remoteexception *         /        @ Override public        void Killself () throws RemoteException {            android.os.Process.killProcess ( Android.os.Process.myPid ());        }
        /**         * Execute Command         *         * @param params command         * @return result         * @throws remoteexception        */@Override public string Command (string params) throws RemoteException {            Commandexecutor executor = commandexecutor.create ( params);            Lock.lock ();            Commandexecutors.add (executor);            Lock.unlock ();            String result = Executor.getresult ();            Lock.lock ();            Commandexecutors.remove (executor);            Lock.unlock ();            return result;        }

Now that the service kills itself and cannot save the current queue task in memory, will the task be discarded? This is certainly not allowed, we can not control in the service but in the control of the task:


The code is as follows:

Package Net.qiujuer.libraries.genius.command;import Android.content.componentname;import Android.content.Context; Import Android.content.intent;import Android.content.serviceconnection;import Android.os.ibinder;import Net.qiujuer.libraries.genius.journal.logutil;import Net.qiujuer.libraries.genius.utils.globalvalue;import Java.util.concurrent.locks.condition;import Java.util.concurrent.locks.lock;import java.util.concurrent.locks.reentrantlock;/** * Created by Genius on 2014/8/13.    * Command execution Model */public class Commandmodel {private static final String TAG = CommandModel.class.getName ();    Call the service interface private static icommandinterface IService = null;  Service link class, for instantiating the service interface private static Serviceconnection conn = new Serviceconnection () {@Override public void            onserviceconnected (componentname name, IBinder service) {ilock.lock ();            IService = ICommandInterface.Stub.asInterface (service);          if (IService! = null) {try {          Icondition.signalall ();                } catch (Exception e) {e.printstacktrace ();            }} else Bindservice ();            Ilock.unlock ();        Logutil.i (TAG, "onserviceconnected");            } @Override public void onservicedisconnected (componentname name) {iservice = null;        Logutil.i (TAG, "onservicedisconnected");    }    };    Lock private static Lock ILock = new Reentrantlock ();    Wait and wake private static Condition icondition = Ilock.newcondition ();    Execution parameters private String parameter;    Whether to cancel testing of private Boolean iscancel; /** * Instantiation * * @param params @param params command parameter eg: "/system/bin/ping", "-C", "4", "-S", "$", "www.qiujuer.net */Public Commandmodel (String ... params) {//check params if (params = = null) throw new        NullPointerException ();        Run StringBuilder sb = new StringBuilder (); for (String Str:params) {sb.append (str);        Sb.append ("");    } This.parameter = Sb.tostring (); /** * Execute Test * * @param model ProcessModel * @return result */public static String command (COMMANDM        Odel model) {//detects whether to cancel test if (model.iscancel) return null;            Check Service if (IService = = null) {Ilock.lock ();            try {icondition.await ();            } catch (Interruptedexception e) {e.printstacktrace ();        } ilock.unlock ();        The String result;        try {result = Iservice.command (Model.parameter);            } catch (Exception e) {e.printstacktrace ();            Bindservice ();        result = command (model);    } return result;        }/** * Start and bind service */private static void Bindservice () {Context context = Globalvalue.getcontext (); Intent Intent = new Intent (context, Commandservice.class);        Context.startservice (Intent);    Context.bindservice (Intent, Conn, context.bind_auto_create);    }/** * Cancel Test */public void Cancel () {Iscancel = true;    }/** * Static initialization * */static {bindservice (); }}
among them:

    public static String command (Commandmodel model) {        //detects whether to cancel test        if (model.iscancel)            return null;        Check Service        if (IService = = null) {            ilock.lock ();            try {                icondition.await ();            } catch (Interruptedexception e) {                e.printstacktrace ();            }            Ilock.unlock ();        }        String result;        try {            result = Iservice.command (Model.parameter);        } catch (Exception e) {            e.printstacktrace ();            Bindservice ();            result = command (model);        }        return result;    }
The callback is used to complete the task execution Method!

Standalone Process Service interface: Icommandinterface.aidl

Interface Icommandinterface {     void killself ();     String command (string params);
Command Performer (actual function implementation in the service): Commandexecutor.java

Package Net.qiujuer.libraries.genius.command;import Net.qiujuer.libraries.genius.journal.logutil;import Net.qiujuer.libraries.genius.utils.toolutil;import Java.io.bufferedreader;import Java.io.IOException;import Java.io.inputstream;import Java.io.inputstreamreader;import Java.io.outputstream;import Java.util.concurrent.locks.lock;import java.util.concurrent.locks.reentrantlock;/** * Created by Genius on 2014/8/13.    * Command line Execution command */class commandexecutor {private static final String TAG = CommandExecutor.class.getName ();    Line break private static final String break_line;    Error buffering private static final byte[] buffer;    Buffer size private static final int buffer_length;    Mutex is required to create a process private static final lock lock = new Reentrantlock ();    Cannot exceed 1 minutes private static final long TIMEOUT = 60000;    Processbuilder private static Processbuilder PRC;    Final private process process;    Final private inputstream in;    Final private InputStream err; Final Private OutputStream Out    Final private StringBuilder Sbreader;    Private BufferedReader binreader = null;    Private InputStreamReader isinreader = null;    Private Boolean IsDone;    Private long startTime;        /** * Static variable initialization */static {break_line = "\ n";        Buffer_length = 128;        BUFFER = new Byte[buffer_length];        Lock.lock ();        PRC = new Processbuilder ();    Lock.unlock (); }/** * Instantiates a commandexecutor * * @param process Process */private commandexecutor (process process)        {//init this.starttime = System.currenttimemillis ();        this.process = process;        Get out = Process.getoutputstream ();        in = Process.getinputstream ();        Err = Process.geterrorstream ();            In if (in! = null) {Isinreader = new InputStreamReader (in);        Binreader = new BufferedReader (Isinreader, buffer_length);        } Sbreader = new StringBuilder (); Start Read thread THread ProcessThread = new Thread (TAG) {@Override public void run () {startread ();        }        };        Processthread.setdaemon (TRUE);    Processthread.start (); }/** * Execute command * * @param param command parameter eg: "/system/bin/ping-c 4-s www.qiujuer.net" */protected S        Tatic commandexecutor Create (String param) {string[] params = Param.split ("");        Commandexecutor ProcessModel = null;            try {lock.lock ();            Process process = Prc.command (params). Redirecterrorstream (True). Start ();        ProcessModel = new Commandexecutor (process);        } catch (IOException e) {e.printstacktrace ();            } finally {//sleep toolutil.sleepignoreinterrupt (100);        Lock.unlock ();    } return ProcessModel;       }/** * Gets whether timeout * * @return Timeout */protected Boolean istimeout () { Return ((System.currenttimemillis ()-startTime) >= TIMEOUT);        }//Read result private void Read () {String str;                Read in try {(str = binreader.readline ()) = null) {sbreader.append (str);            Sbreader.append (Break_line);            }} catch (Exception e) {String err = e.getmessage ();            if (err! = null && err.length () > 0) {logutil.e (TAG, "Read Exception:" + err);             }}}/** * Start thread for asynchronous read results */private void Startread () {//while to End while (true) {                try {process.exitvalue ();                Read last read ();            Break            } catch (Illegalthreadstateexception e) {read ();        } toolutil.sleepignoreinterrupt (50);        }//read end int len; if (in = null) {try {while (len = In.read (BUFFER)) > 0) {logutil.d (TAG, "read End:" + len);                }} catch (IOException e) {String err = e.getmessage ();            if (err! = null && err.length () > 0) logutil.e (TAG, "Read Thread IOException:" + err);        }}//close close ();        Destroy Destroy ();    Done IsDone = true; }/** * Get execution Results * * @return Results */protected String GetResult () {//until startread en w        Hile (!isdone) {toolutil.sleepignoreinterrupt (200);        }//return if (sbreader.length () = = 0) return null;    else return sbreader.tostring ();                }/** * Close all streams */private void Close () {//close out if (out! = null) {try {            Out.close ();            } catch (IOException e) {e.printstacktrace ();      }  }//err if (err! = null) {try {err.close ();            } catch (IOException e) {e.printstacktrace ();            }}//in if (in! = null) {try {in.close ();            } catch (IOException e) {e.printstacktrace ();            }} if (Isinreader! = null) {try {isinreader.close ();            } catch (IOException e) {e.printstacktrace ();            }} if (Binreader! = null) {try {binreader.close ();            } catch (IOException e) {e.printstacktrace ();        }}}/** * destroy * * private void Destroy () {String str = process.tostring ();            try {int i = str.indexof ("=") + 1;            Int J = str.indexof ("]");            str = str.substring (i, j);            int pid = Integer.parseint (str); Try {android.os.Process.killProcess (PID);                } catch (Exception e) {try {Process.destroy ();                } catch (Exception ex) {ex.printstacktrace ();        }}} catch (Exception e) {e.printstacktrace (); }    }}

All right, this is the end of the use of violence, for the execution of command parameters can be said to be the perfect way to execute, in such a way I do ping test reached 100,000 times, concurrently reach 500 tasks simultaneously execute no problem, the test device is: Meizu M9.

This code I have packaged into my own class library, and open source to GitHub; Address: genius-android
I hope you can migrate my project a lot, the library also comes with a complete log system that I have developed, and will add other things later, which is more relevant than chip processing (blur, etc.)



[Java] [Android] [Process] The service of violence can solve all, violent ways to execute command line statements

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.