1. 程式人生 > >Android上app_process啟動java程序

Android上app_process啟動java程序

  Java程式是跨平臺的,由JVM虛擬機器執行位元組碼。Android應用程式開發也是Java,但是都是執行在Context環境下的。獨立的Java程式能夠在Android上獨立執行?

  這裡不介紹Android啟動過程中,app_process從哪個程序fork處理,也不介紹app_process啟動App的過程。僅介紹app_process啟動純Java程式的相關知識。

一、HelloWorld示例

1. 源程式

  編寫一個hellworld 的Java程式,並且編譯成.class檔案,簡單得沒啥可說的。

public class Helloworld {
    public
static void main(String[]args){ System.out.println("Hello, I am started by app_process!"); } }

  Android對Java虛擬機器做了修改,即使用自己的dalvik虛擬機器(後來的ART)。因此,.class的位元組碼在Dalvik虛擬機器上是不能執行的。Android Platform tool為我們提供了生成Android上可執行jar(Dex)工具:dx。編譯命令如下:

//編譯,這裡主要是Platform tool上用的是Java 7,所以顯式指定1.7
javac -source 1.7 -target 1.7 C:\Users
\Venscor\Desktop\app_process\dump.java //生成dex,當然生成jar在Android上也是可執行的 dx --dex --output=C:\Users\Venscor\Desktop\app_process\Hellworld.dex Helloworld.class

2. 執行

  app_process引數格式如下:

app_process [vm-options] cmd-dir [options] start-class-name [main-options]

  app_process執行引數居然沒有help,萬惡的開發者。這塊要麼查資料,要麼看原始碼。從網上找的對引數解釋如下:

vm-options – VM 選項
cmd-dir –父目錄 (/system/bin)
options –執行的引數 :
    –zygote
    –start-system-server
    –application (api>=14)
    –nice-name=nice_proc_name (api>=14)
start-class-name –包含main方法的主類  (com.android.commands.am.Am)
main-options –啟動時候傳遞到main方法中的引數

  將我們前面編譯得到的dex(jar)檔案push到/data/local/tmp資料夾下,構建app_process執行引數:

app_process -Djava.class.path=Helloworld.dex  /data/local/tmp Helloworld

  切換/data/local/tmp目錄下執行,HelloWorld就成功執行啦!

二、被啟動的Java的Pid, Uid與許可權

  上面展示了使用app_process在Android啟動獨立的Java程序的Demo。那麼,被啟動的Java程式作為一個獨立的程序,其從何處fork而來,Uid為多少,對應什麼級別許可權就是下面要解決的問題。

  為了能夠檢視app_process啟動的Java程式的程序資訊,希望demo程式不立馬執行結束,以便能夠通過ps檢視程序資訊。修改上面的demo程式,變成死迴圈讓程式持久存活,並先後啟動兩個這樣的Java程式。

  通過上面程序資訊可以看到,每次Java程式執行時,系統都會給其分配一個pid,並且程序名都是app_process。(至於為什麼要這麼命名,不清楚。。。)

  通過追蹤ppid,還能發現啟動的java程序源自何處,即怎麼fork出來的,即:/init–>/sbin/adbd–>/system/bin/sh–>app_process(Java程序),也就是說,啟動的Java程序是從/system/bin/sh(shell)fork出來的。

這裡寫圖片描述

  知道了相應的pid,就可以通過pid檢視程序資訊,對應的shell命令為:cat /proc/[pid]/status.

這裡寫圖片描述

  通過上面資訊可以看到,app_process啟動的Java程式執行的uid是和pid是2000,也就是shell 的Uid,所以app_process啟動的Java程式擁有shell級別的許可權,下面就此來做個驗證。

三、啟動的Java程式擁有的許可權及Uid

  adb shell中,dumpsys activity命令是檢視Activity棧資訊的,只有shell許可權(可能有shell許可權也不行,必須Uid為shell,沒有去看)才能呼叫。所以可以通過這個來驗證啟動的Java程式是否真的運行於shell的Uid下,測試原始碼如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class dump {
    public static void main(String[]args){
        String cmd="dumpsys activity";
        System.out.println("Hello, I am started by app_process!");
        try {
            Process p=Runtime.getRuntime().exec(cmd);
            BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
            String readLine=br.readLine();
            while(readLine!=null){
                System.out.println(readLine);
                readLine=br.readLine();
            }
            if(br!=null){
                br.close();
            }
            p.destroy();
            p=null;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

  和前面demo一樣編譯到Android下執行,檢視結果,發現可以正常輸出,說明app_process啟動的Java程式的確具有shell級別的許可權(其實其Uid就是shell)。

這裡寫圖片描述

  總結: 上面說明了app_process啟動Java的相關知識,至於有啥重要用途,後續會陸續給出。