当前位置: 首页 > news >正文

[Java][Android][Process] ProcessBuilder与Runtime差别

在Android中想要进行Ping,在不Root机器的情况下似乎还仅仅能进行底层命调用才干实现。

由于在Java中要进行ICMP包发送须要Root权限。


于是仅仅能通过创建进程来攻克了。创建进程在Java中有两种方式,分别为:

1. 调用ProcessBuilder的构造函数后运行start()
2. 用Runtime.getRuntime().exec()方法运行


经过使用后发现两者有差别可是也并非非常大,两个样例说明:


1.调用ProcessBuilder的构造函数后运行start():

Process process = new ProcessBuilder("/system/bin/ping").redirectErrorStream(true).start();
OutputStream stdout = process.getOutputStream();
InputStream stdin = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));


2.用Runtime.getRuntime().exec()方法运行:

Process process = Runtime.getRuntime().exec("/system/bin/ping");
OutputStream stdout = process.getOutputStream();
InputStream stderr = process.getErrorStream();
InputStream stdin = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));
BufferedReader err= new BufferedReader(new InputStreamReader(stderr));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdout));

两者在运行效率上没啥差别,可能是我没有发现。

两种測试的差别在于能否够重定向错误流。


使用ProcessBuilder,能够通过redirectErrorStream(true)将错误输出流转移到标准输出流中,这样使用一次process.getInputStreamReader()就能读出该进程的全部输出。

而使用Runtime.getRuntime().exec()方法时。错误的输出流还需通过process.getErrorStream()来获得。


分享一个自己集合的一个进程运行后销毁的类:

import java.io.InputStream;
import java.io.OutputStream;

public class ProcessModel {

    /**
     * 通过Android底层实现进程关闭
     *
     * @param process
     */
    public static void killProcess(Process process) {
        int pid = getProcessId(process.toString());
        if (pid != 0) {
            try {
                android.os.Process.killProcess(pid);
            } catch (Exception e) {
                try {
                    process.destroy();
                } catch (Exception ex) {
                }
            }
        }
    }

    /**
     * 获取当前进程的ID
     *
     * @param str
     * @return
     */
    public static int getProcessId(String str) {
        try {
            int i = str.indexOf("=") + 1;
            int j = str.indexOf("]");
            String cStr = str.substring(i, j).trim();
            return Integer.parseInt(cStr);
        } catch (Exception e) {
            return 0;
        }
    }


    /**
     * 关闭进程的全部流
     *
     * @param process
     */
    public static void closeAllStream(Process process) {
        try {
            InputStream in = process.getInputStream();
            if (in != null)
                in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            InputStream in = process.getErrorStream();
            if (in != null)
                in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            OutputStream out = process.getOutputStream();
            if (out != null)
                out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 销毁一个进程
     *
     * @param process
     */
    public static void processDestroy(Process process) {
        if (process != null) {
            try {
                if (process.exitValue() != 0) {
                    closeAllStream(process);
                    killProcess(process);
                }
            } catch (IllegalThreadStateException e) {
                closeAllStream(process);
                killProcess(process);
            }
        }
    }


    /**
     * 通过线程进行异步销毁
     *
     * @param process
     */
    public static void asyncProcessDestroy(final Process process) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                processDestroy(process);
            }
        });
        thread.setDaemon(true);
        thread.start();
    }
}



奇怪的是,当使用线程进行大量的进程创建。最后达到一定数量(大约为1000个左右)的时候将会出现无法创建进程的情况;

此情况我不知怎么解决,自己想的是弄一个线程池里边放20个已经创建的进程,而外部的线程反复利用以及创建的进程,不知这样是否可行?

望大家探讨一下解决方法。谢谢了。

相关文章:

  • NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成...
  • 服务器虚拟化的十大谎言
  • cacti找不到网卡的解决方法
  • Java并发3:线程
  • 技术部门怎么年终考核最合理?
  • python机器学习实战(二)
  • 生成验证码
  • 【Spring Boot】19.集成消息
  • Visio2010建立ER图并直接导出为SQL语句
  • tomcat架构分析和源码解读
  • 2015博客升级记(五):CentOS 7.1编译安装PHP7
  • Git的一些常用操作
  • 正确配置jstl的maven依赖,jar包冲突的问题终于解决啦
  • Java开发集合定义及案例详解
  • nginx请求转发
  • [译]前端离线指南(上)
  • 2017-09-12 前端日报
  • ECS应用管理最佳实践
  • ES2017异步函数现已正式可用
  • Intervention/image 图片处理扩展包的安装和使用
  • JavaScript类型识别
  • LintCode 31. partitionArray 数组划分
  • PhantomJS 安装
  • Vue.js源码(2):初探List Rendering
  • vue自定义指令实现v-tap插件
  • 基于组件的设计工作流与界面抽象
  • 前端技术周刊 2019-01-14:客户端存储
  • 跳前端坑前,先看看这个!!
  • 用mpvue开发微信小程序
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (SpringBoot)第二章:Spring创建和使用
  • (备忘)Java Map 遍历
  • (论文阅读11/100)Fast R-CNN
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转载)OpenStack Hacker养成指南
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .net打印*三角形
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • .NET简谈设计模式之(单件模式)
  • @html.ActionLink的几种参数格式
  • [BZOJ3211]:花神游历各国(小清新线段树)
  • [c#基础]值类型和引用类型的Equals,==的区别
  • [C/C++]数据结构 循环队列
  • [C++]AVL树怎么转
  • [CentOs7]图形界面
  • [CSS]浮动
  • [flume$2]记录一个写自定义Flume拦截器遇到的错误
  • [LeetCode] 626. 换座位
  • [LeetCode]-225. 用队列实现栈-232. 用栈实现队列
  • [LeetCode]—Longest Palindromic Substring 最长回文子串