java的runtime.exec创建的线程被挂起的解决办法。

来源:互联网 发布:国家一级蜥蜴知多少 编辑:程序博客网 时间:2024/06/05 05:17
 

java class process方法exec调用方法proccess proc.exec(command)。当command的输出内容过大时(OS的I/O buffer容纳不下输出流时),程序会被挂起。解决此内问题的方法将command的输出流proc.getErrorStream(),proc.getInputStream()清空。以下为一示例, linux7.2,jdk1.5.0_06下编译通过。

/*************************************************************************************
*Process exec method: clearn output stream first
*by Benny Zhou
*2/27/2007
**************************************************************************************/
/*
*Runtime.exec method. A few things to keep in mind when using this:
*1. Always read from the streams prior to calling waitFor.
*Otherwise you could end up waiting forever on Windows and other OS platforms whose I/O buffers can¡¯t store enough from
*standard out and standard error to ensure the program has finished. These platforms will pause the execution of whatever
*is running until something reads the buffered content from standard  out and standard error. All platforms suffer from
*this, but some platforms have larger buffers than  others. Needless to say, always read from the streams first.
*2. Always read from standard error first.
*If you read from standard out first and the process only writes to standard error, you¡¯ll hang forever waiting to read.
*IF you read from standard error first, you¡¯ll always be okay on these platforms because the OS seems to shutdown standard
*error.
*/
import java.io.*;
import java.lang.*;  
import java.util.*;

public class ProcessExec
{

        static void drainInBackground(final InputStream is) {
                 new Thread(new Runnable(){
                public void run(){
                        try{
                             while( is.read() >= 0 );
                        } catch(IOException e){
                        }
                }
                }).start();
        }

        public void UnpackupDir(String rootpath,String tarname,String backupType) throws IOException
        {
                String unpackdir=rootpath;
                String strUnpackName = "";
                Runtime r=Runtime.getRuntime();
                Process prog=null;

                strUnpackName="./restoreoptarfile.sh "+unpackdir +" "+tarname+" "+backupType;
                try
                {       System.out.println("========before process.exec()");
                        prog=r.exec(strUnpackName);
                        System.out.println("========after process.exec()");
                        System.out.println("========before process.waitFor()");


                        //==========method 2, clearn output stream first
                        drainInBackground(prog.getErrorStream());
                        drainInBackground(prog.getInputStream());


                        /*//==========method 1. get streams and standart out put first, still need clearn output stream
                        BufferedReader stderr = new BufferedReader(new InputStreamReader(prog.getErrorStream()));
                        String LineErr = stderr.readLine();

                        BufferedReader inpbuildtar = new BufferedReader(new InputStreamReader(prog.getInputStream()));
                        String LINE = inpbuildtar.readLine();
                         while (LineErr !=null)
                        {
                                System.out.println("LineError>>>"+LineErr);
                                LineErr = stderr.readLine();
                        }

                        while (LINE != null)
                        {
                                System.out.println("Line>>>"+LINE);
                                LINE = inpbuildtar.readLine();

                        }
                        */

                        int progEnd = prog.waitFor();
                //      inpbuildtar.close();
                //      stderr.close();

                        System.out.println("========after process.waitFor()");
                        System.out.println("========before Runtime.gc()");
                        r.gc();
                        String unpackfiledir = unpackdir +File.separator+tarname;
                        File unpackfile= new File(unpackfiledir);
                        File dirUnpack = new File(unpackdir +File.separator+backupType+File.separator+"structure"+File.separator+"wbxsite.stc");
                        if(!unpackfile.exists() || !dirUnpack.exists())
                        {
                                System.out.println("ERROR>> Tar file do not unpack  please check the parameter !");
                                System.out.println("ERROR>> Please make sure you have executed the command: <chmod +x *.sh>");
                                System.exit(0);
                        }
                        else
                        {}
                }
                catch(Exception e)
                {
                        System.out.println("ERROR>> Tar file is not unpacked successfully!");
                        System.exit(0);
                }
        }

        public static void main(String args[])
        {
                ProcessExec proexec = new ProcessExec();               
                String str_rootpath="/webex_doc/dfs/migrate/backup";
                String str_tarname="everest@wconfig%T25L%2%2@400006466.tar";
                String str_backupType="everest";
                           
                try
                {
                        proexec.UnpackupDir(str_rootpath,str_tarname,str_backupType);
                }
                catch (Exception e)
                {
                        String err = e.getMessage();
                        System.out.println(err);
                        System.exit(0);
                }
        }