最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android應(yīng)用框架之應(yīng)用啟動過程詳解

 更新時間:2016年11月06日 11:47:35   作者:李牙刷兒_  
這篇文章主要為大家詳細介紹了Android應(yīng)用框架,應(yīng)用啟動過程,具有一定的參考價值,感興趣的小伙伴們可以參考一下

在Android的應(yīng)用框架中,ActivityManagerService是非常重要的一個組件,盡管名字叫做ActivityManagerService,但通過之前的博客介紹,我們知道,四大組件的創(chuàng)建都是有AMS來完成的,其實不僅是應(yīng)用程序中的組件,連Android應(yīng)用程序本身也是AMS負責(zé)啟動的。AMS本身運行在一個獨立的進程中,當(dāng)系統(tǒng)決定要在一個新的進程中啟動一個Activity或者Service時就會先啟動這個進程。而AMS啟動進程的過程是從startProcessLocked啟動的。

1.ActivityManagerService.startProcessLocked

public final class ActivityManagerService extends ActivityManagerNative 
    implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { 
  ...... 
  private final void startProcessLocked(ProcessRecord app, 
        String hostingType, String hostingNameStr) { 
    ...... 
    try { 
      int uid = app.info.uid; 
      int[] gids = null; 
      try { 
        gids = mContext.getPackageManager().getPackageGids( 
          app.info.packageName); 
      } catch (PackageManager.NameNotFoundException e) { 
        ...... 
      } 
      ...... 
      int debugFlags = 0; 
      ...... 
      int pid = Process.start("android.app.ActivityThread", 
        mSimpleProcessManagement ? app.processName : null, uid, uid, 
        gids, debugFlags, null); 
      ...... 
    } catch (RuntimeException e) { 
      ...... 
    } 
  } 
  ...... 
} 

可以看到,函數(shù)會調(diào)用Process.start函數(shù)來創(chuàng)建一個進程,其中第一個參數(shù)”android.app.ActivityThread”是需要加載的類,而在完成這個類的加載之后就會運行ActivityThread.main函數(shù)。

2.Process.start

public class Process {
  ......
  public static final int start(final String processClass,
    final String niceName,
    int uid, int gid, int[] gids,
    int debugFlags,
    String[] zygoteArgs)
  {
    if (supportsProcesses()) {
      try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
          debugFlags, zygoteArgs);
      } catch (ZygoteStartFailedEx ex) {
        ......
      }
    } else {
      ......
      return 0;
    }
  }
  ......
}

這個函數(shù)最后會調(diào)用startViaZygote來創(chuàng)建進程,而Zygote正是Android孵化進程的服務(wù),所有的進程都是通過Zygotefork出來的,所以這里創(chuàng)建進程的任務(wù)又落到了Zygote頭上了。

3.Process.startViaZygote

public class Process {
  ......
  private static int startViaZygote(final String processClass,
      final String niceName,
      final int uid, final int gid,
      final int[] gids,
      int debugFlags,
      String[] extraArgs)
      throws ZygoteStartFailedEx {
    int pid;

    synchronized(Process.class) {
      ArrayList<String> argsForZygote = new ArrayList<String>();

      // --runtime-init, --setuid=, --setgid=,
      // and --setgroups= must go first
      argsForZygote.add("--runtime-init");
      argsForZygote.add("--setuid=" + uid);
      argsForZygote.add("--setgid=" + gid);
      if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
        argsForZygote.add("--enable-safemode");
      }
      if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
        argsForZygote.add("--enable-debugger");
      }
      if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
        argsForZygote.add("--enable-checkjni");
      }
      if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
        argsForZygote.add("--enable-assert");
      }

      //TODO optionally enable debuger
      //argsForZygote.add("--enable-debugger");

      // --setgroups is a comma-separated list
      if (gids != null && gids.length > 0) {
        StringBuilder sb = new StringBuilder();
        sb.append("--setgroups=");

        int sz = gids.length;
        for (int i = 0; i < sz; i++) {
          if (i != 0) {
            sb.append(',');
          }
          sb.append(gids[i]);
        }

        argsForZygote.add(sb.toString());
      }

      if (niceName != null) {
        argsForZygote.add("--nice-name=" + niceName);
      }

      argsForZygote.add(processClass);

      if (extraArgs != null) {
        for (String arg : extraArgs) {
          argsForZygote.add(arg);
        }
      }
      pid = zygoteSendArgsAndGetPid(argsForZygote);
    }
  }
  ......
}

函數(shù)里面最為重要的工作就是組裝argsForZygote參數(shù),這些參數(shù)將告訴Zygote具體的啟動選項,例如”–runtime-init”就表示要為新啟動的運行程序初始化運行庫。然后調(diào)用zygoteSendAndGetPid函數(shù)進一步操作。

4.Process.zygoteSendAndGetPid

public class Process {
  ......

  private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
      throws ZygoteStartFailedEx {
    int pid;

    openZygoteSocketIfNeeded();

    try {
      /**
      * See com.android.internal.os.ZygoteInit.readArgumentList()
      * Presently the wire format to the zygote process is:
      * a) a count of arguments (argc, in essence)
      * b) a number of newline-separated argument strings equal to count
      *
      * After the zygote process reads these it will write the pid of
      * the child or -1 on failure.
      */

      sZygoteWriter.write(Integer.toString(args.size()));
      sZygoteWriter.newLine();

      int sz = args.size();
      for (int i = 0; i < sz; i++) {
        String arg = args.get(i);
        if (arg.indexOf('\n') >= 0) {
          throw new ZygoteStartFailedEx(
            "embedded newlines not allowed");
        }
        sZygoteWriter.write(arg);
        sZygoteWriter.newLine();
      }

      sZygoteWriter.flush();

      // Should there be a timeout on this?
      pid = sZygoteInputStream.readInt();

      if (pid < 0) {
        throw new ZygoteStartFailedEx("fork() failed");
      }
    } catch (IOException ex) {
      ......
    }
    return pid;
  }
  ......
}

這里的sZygoteWriter

是一個Socket寫入流,是由openZygoteSocketIfNeeded函數(shù)打開的。而這個Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit類在runSelectLoopMode函數(shù)偵聽的。這個類會返回一個ZygoteConnection實例,并執(zhí)行ZygoteConnection的runOnce函數(shù)。

5.ZygoteConnection.runOnce

class ZygoteConnection {
  ......

  boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
      args = readArgumentList();
      descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
      ......
      return true;
    }

    ......

    /** the stderr of the most recent request, if avail */
    PrintStream newStderr = null;

    if (descriptors != null && descriptors.length >= 3) {
      newStderr = new PrintStream(
        new FileOutputStream(descriptors[2]));
    }

    int pid;

    try {
      parsedArgs = new Arguments(args);

      applyUidSecurityPolicy(parsedArgs, peer);
      applyDebuggerSecurityPolicy(parsedArgs);
      applyRlimitSecurityPolicy(parsedArgs, peer);
      applyCapabilitiesSecurityPolicy(parsedArgs, peer);

      int[][] rlimits = null;

      if (parsedArgs.rlimits != null) {
        rlimits = parsedArgs.rlimits.toArray(intArray2d);
      }

      pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
        parsedArgs.gids, parsedArgs.debugFlags, rlimits);
    } catch (IllegalArgumentException ex) {
      ......
    } catch (ZygoteSecurityException ex) {
      ......
    }

    if (pid == 0) {
      // in child
      handleChildProc(parsedArgs, descriptors, newStderr);
      // should never happen
      return true;
    } else { /* pid != 0 */
      // in parent...pid of < 0 means failure
      return handleParentProc(pid, descriptors, parsedArgs);
    }
  }
  ......
}

真正創(chuàng)建進程的代碼在Zygote.forkAndSpecialize,通過Zygote來fork出一個新的進程作為應(yīng)用進程。fork函數(shù)會有兩個返回,其中一個在父進程,一個在子進程,其中自進程的進程號會為0,所以按照上面的代碼,這里會執(zhí)行handleChildProc。

6.ZygoteConnection.handleChildProc

class ZygoteConnection {
  ......
  private void handleChildProc(Arguments parsedArgs,
      FileDescriptor[] descriptors, PrintStream newStderr)
      throws ZygoteInit.MethodAndArgsCaller {
    ......
    if (parsedArgs.runtimeInit) {
      RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
    } else {
      ......
    }
  }
  ......
}

因為在創(chuàng)建的時候傳入了“–runtime-init”,所以這里會運行RuntimeInit.zygoteInit。

public class RuntimeInit {
  ......

  public static final void zygoteInit(String[] argv)
      throws ZygoteInit.MethodAndArgsCaller {
    // TODO: Doing this here works, but it seems kind of arbitrary. Find
    // a better place. The goal is to set it up for applications, but not
    // tools like am.
    System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
    System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));

    commonInit();
    zygoteInitNative();

    int curArg = 0;
    for ( /* curArg */ ; curArg < argv.length; curArg++) {
      String arg = argv[curArg];

      if (arg.equals("--")) {
        curArg++;
        break;
      } else if (!arg.startsWith("--")) {
        break;
      } else if (arg.startsWith("--nice-name=")) {
        String niceName = arg.substring(arg.indexOf('=') + 1);
        Process.setArgV0(niceName);
      }
    }

    if (curArg == argv.length) {
      Slog.e(TAG, "Missing classname argument to RuntimeInit!");
      // let the process exit
      return;
    }

    // Remaining arguments are passed to the start class's static main

    String startClass = argv[curArg++];
    String[] startArgs = new String[argv.length - curArg];

    System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
    invokeStaticMain(startClass, startArgs);
  }
  ......
}

這里有兩個關(guān)鍵的函數(shù)調(diào)用,一個是zygoteInitNative函數(shù)調(diào)用,一個是invokeStaticMain函數(shù)調(diào)用,前者就是執(zhí)行Binder驅(qū)動程序初始化的相關(guān)工作了,正是由于執(zhí)行了這個工作,才使得進程中的Binder對象能夠順利地進行Binder進程間通信,而后一個函數(shù)調(diào)用,就是執(zhí)行進程的入口函數(shù),這里就是執(zhí)行startClass類的main函數(shù)了,而這個startClass即是我們在Step 1中傳進來的”android.app.ActivityThread”值,表示要執(zhí)行android.app.ActivityThread類的main函數(shù)。

7. Zygote.invokeStaticMain

public class ZygoteInit {
  ......

  static void invokeStaticMain(ClassLoader loader,
      String className, String[] argv)
      throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;

    try {
      cl = loader.loadClass(className);
    } catch (ClassNotFoundException ex) {
      ......
    }

    Method m;
    try {
      m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
      ......
    } catch (SecurityException ex) {
      ......
    }

    int modifiers = m.getModifiers();
    ......

    /*
    * This throw gets caught in ZygoteInit.main(), which responds
    * by invoking the exception's run() method. This arrangement
    * clears up all the stack frames that were required in setting
    * up the process.
    */
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
  }
  ......
}

從代碼中可以看到,通過ClassLoader加載對應(yīng)的android.app.ActivityThread類,然后再獲取到對應(yīng)的main函數(shù)句柄,最后調(diào)用該類的main函數(shù)。不過這里的調(diào)用方式比較有意思,不知直接調(diào)用,而是通過拋出一個異常。這樣做的方式是為了清空堆棧,讓系統(tǒng)認為新進程是從ActivityThread的main函數(shù)開始的。

8.ActivityThread.main

public final class ActivityThread {
  ......

  public static final void main(String[] args) {
    SamplingProfilerIntegration.start();

    Process.setArgV0("<pre-initialized>");

    Looper.prepareMainLooper();
    if (sMainThreadHandler == null) {
      sMainThreadHandler = new Handler();
    }

    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (false) {
      Looper.myLooper().setMessageLogging(new
        LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    Looper.loop();

    if (Process.supportsProcesses()) {
      throw new RuntimeException("Main thread loop unexpectedly exited");
    }

    thread.detach();
    String name = (thread.mInitialApplication != null)
      ? thread.mInitialApplication.getPackageName()
      : "<unknown>";
    Slog.i(TAG, "Main thread of " + name + " is now exiting");
  }

  ......
}

從這里我們可以看出,這個函數(shù)首先會在進程中創(chuàng)建一個ActivityThread對象,然后進入消息循環(huán)中,這樣,我們以后就可以在這個進程中啟動Activity或者Service了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android版本更新實例詳解

    Android版本更新實例詳解

    這篇文章主要介紹了Android版本更新實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Android Button的基本用法詳解及簡單實例

    Android Button的基本用法詳解及簡單實例

    這篇文章主要介紹了Android Button的基本用法詳解及簡單實例的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • 淺談Okhttp去除請求頭user-agent

    淺談Okhttp去除請求頭user-agent

    本篇文章主要介紹了淺談Okhttp去除請求頭user-agent,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • android利用xml實現(xiàn)分割線

    android利用xml實現(xiàn)分割線

    這篇文章主要介紹了android利用xml實現(xiàn)分割線的方法,如何用xml產(chǎn)生一個分割線?感興趣的小伙伴們可以參考一下
    2015-12-12
  • 詳解Android如何自定義view實現(xiàn)圓形進度條

    詳解Android如何自定義view實現(xiàn)圓形進度條

    Android中實現(xiàn)進度條有很多種方式,自定義進度條一般是繼承progressBar或繼承view來實現(xiàn)。本文將介紹通過自定義View實現(xiàn)的圓形進度條,感興趣的可以動手試一試
    2022-01-01
  • Android使用AsyncTask下載圖片并顯示進度條功能

    Android使用AsyncTask下載圖片并顯示進度條功能

    這篇文章主要介紹了Android使用AsyncTask下載圖片并顯示進度條功能,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-02-02
  • 從源碼分析Android的Glide庫的圖片加載流程及特點

    從源碼分析Android的Glide庫的圖片加載流程及特點

    這篇文章主要介紹了從源碼分析Android的Glide庫的圖片加載流程及特點,Glide庫是Android下一款人氣很高的多媒體資源管理庫,特別是在處理gif加載方面受到眾多開發(fā)者青睞,需要的朋友可以參考下
    2016-04-04
  • Android中g(shù)son、jsonobject解析JSON的方法詳解

    Android中g(shù)son、jsonobject解析JSON的方法詳解

    JSON即JavaScript Object Natation, 它是一種輕量級的數(shù)據(jù)交換格式, 與XML一樣, 是廣泛被采用的客戶端和服務(wù)端交互的解決方案.接下來由腳本之家小編給大家介紹Android中g(shù)son、jsonobject解析JSON的方法,感興趣的朋友一起學(xué)習(xí)吧
    2016-02-02
  • Android View轉(zhuǎn)換為Bitmap實現(xiàn)應(yīng)用內(nèi)截屏功能

    Android View轉(zhuǎn)換為Bitmap實現(xiàn)應(yīng)用內(nèi)截屏功能

    這篇文章主要介紹了Android View轉(zhuǎn)換為Bitmap實現(xiàn)應(yīng)用內(nèi)截屏功能,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-09-09
  • Android strings.xml使用方法及技巧

    Android strings.xml使用方法及技巧

    本文主要介紹Android strings.xml,這里對strings.xml文件的使用和一些小技巧做了總結(jié),有興趣的同學(xué)可以看下
    2016-08-08

最新評論

遵义市| 凤庆县| 青海省| 宝兴县| 封开县| 梅河口市| 潼南县| 秦安县| 恩施市| 遂昌县| 南通市| 兴文县| 万源市| 临清市| 兖州市| 读书| 读书| 古蔺县| 澳门| 赤壁市| 阜康市| 建始县| 遵义市| 峨边| 德兴市| 卢龙县| 承德市| 昭苏县| 历史| 霸州市| 桂林市| 河曲县| 北辰区| 芜湖市| 团风县| 蓝山县| 仲巴县| 遂川县| 余干县| 安远县| 镇平县|