守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 1547|回复: 1

[Android] 解密ADT第四篇-编译源码

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    51788
    钢镚
    1422

    开源英雄守望者

    发表于 2015-1-19 10:49:33 | 显示全部楼层 |阅读模式

          经过前面三篇的介绍,我相信大家应该知道ADT在编译 打包 AIR FOR ANDROID项目的时候的整个工作流程,所以关于流程原理上的东西 在这里就不多赘述了,ADT编译android源码相比编译资源来说就简单很多,大家直接看源代码注释就能看明白.这一篇分析的是 ADT操作androidSD之中的dx工具把 一堆jar文件编译成dex文件的操作过程,我们都知道 每一个apk文件都需要一个dex文件,而dex文件则是可以被android设备直接执行的文件,就类似与swf文件对于flash player而言.对于想了解更多android程序原理和结构的同学,我推荐大家去购买由国内知名安全论坛看雪学院出品的一本超级好书:android软件安全与逆向分析.

    不够这本书需要一定的android基础.现在我们知道dex文件便是android设备最终可执行的文件 那么我们的ADT是如何生成dex文件的呢?下面我们直接看代码.


    • ADT编译android项目源码
      1. //AppEntry_release.jar 里面包括了默认的启动activity样本代码
      2. InputStream inClsJarStream;
      3. if ((m_configType.equals("apk")) || (m_configType.equals("apk-emulator")) || (m_configType.equals("apk-captive-runtime")))
      4. {
      5.     inClsJarStream = getClass().getResourceAsStream("Dex/AppEntry_release.jar");
      6. }
      7. else
      8. {
      9.     InputStream inClsJarStream;
      10.     if ((m_configType.equals("apk-debug")) || (m_configType.equals("apk-profile")))
      11.     {
      12.         inClsJarStream = getClass().getResourceAsStream("Dex/AppEntry_debug.jar");
      13.     }
      14.     else
      15.     {
      16.         throw new IOException("Unknown APK Config Type");
      17.     }
      18. }
      19. InputStream inClsJarStream;
      20. File tempDir = Utils.createTempDirectory(this.OsTempDir);
      21. tempDir.deleteOnExit();

      22. //新建一个jar 编译进去APK的jar
      23. String inputJarPath = tempDir.getCanonicalPath() + "/inputJAR.jar";
      24. //生成的dex可执行文件名
      25. String outputDexPath = tempDir.getCanonicalPath() + "/outputDEX.dex";
      26. //新建一个jar  运行时框架库
      27. String flashRuntimeExtensionsJarPath = tempDir.getCanonicalPath() + "/FlashRuntimeExtensions.jar";

      28. File inputJar = new File(inputJarPath);
      29. OutputStream outTmpClsJarStream = new FileOutputStream(inputJar);
      30. byte[] buf = new byte[1024];
      31. int len;
      32. //AppEntry_release.jar写入新建的inputJAR.jar
      33. while ((len = inClsJarStream.read(buf)) > 0)
      34.     outTmpClsJarStream.write(buf, 0, len);
      35. outTmpClsJarStream.close();
      36. inClsJarStream.close();

      37. //把Dex/FlashRuntimeExtensions.jar写入新建的FlashRuntimeExtensions.jar
      38. InputStream inFlashRuntimeJarStream = getClass().getResourceAsStream("Dex/FlashRuntimeExtensions.jar");
      39. File flashRuntimeExtensionsJar = new File(flashRuntimeExtensionsJarPath);
      40. OutputStream outTmpFlashRuntimeJarStream = new FileOutputStream(flashRuntimeExtensionsJar);
      41. while ((len = inFlashRuntimeJarStream.read(buf)) > 0)
      42.     outTmpFlashRuntimeJarStream.write(buf, 0, len);
      43. outTmpFlashRuntimeJarStream.close();
      44. inFlashRuntimeJarStream.close();
      45. String dxJarPath;
      46. String dxJarPath;
      47. //获取编译源码工具  它就是androidSDK的dx.jar工具.
      48. if (getAndroidSDKDirectory() != null)
      49. {
      50.     dxJarPath = getAndroidSDKPlatformToolPath() + File.separator + "lib" + File.separator + "dx.jar";
      51. }
      52. else
      53. {
      54.     dxJarPath = Utils.getSDKLibDir() + File.separator + "android" + File.separator + "bin" + File.separator + "dx.jar";
      55. }
      56. if (!new File(dxJarPath).exists()) {
      57.     throw new SDKDamagedException(dxJarPath);
      58. }
      59. List dexCommand = new LinkedList();
      60. //调用java执行dx.jar程序
      61. dexCommand.add("java");

      62. //制定java虚拟机内存大小
      63. //-----------------------------------------------------
      64. //解密JAV内存不足:这里便是ADT获取java启动内存限制参数的位置
      65. //只要在 sdk/bin 下的 adt.bat 或者 adt文件中
      66. //加入 -Xmx512M或者-Xmx1024M
      67. //便可拜托困扰我们已久的 java 内存爆掉的问题.
      68. //------------------------------------------------------
      69. for (String vmArg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
      70.     if ((vmArg.startsWith("-Xms")) || (vmArg.startsWith("-Xmx"))) {
      71.         dexCommand.add(vmArg);
      72.     }
      73. }
      74. dexCommand.add("-jar");
      75. dexCommand.add(dxJarPath);
      76. //制定输出dex文件
      77. dexCommand.add("--dex");
      78. //指定输出路径
      79. //tempDir.getCanonicalPath() + "/outputDEX.dex"
      80. dexCommand.add("--output=" + outputDexPath);
      81. //AppEntry_release.jar
      82. dexCommand.add(inputJarPath);

      83. //上上一篇 aapt编译的资源jar:resources.jar
      84. if (this.m_resourceJar != null)
      85. {
      86.     dexCommand.add(this.m_resourceJar.getCanonicalPath());
      87. }
      88. //若带运行时 则加入 android/lib/runtimeClasses.jar
      89. //这个在AIRSDK中  AIRSDK/lib/android/lib
      90. if (hasCaptiveRuntime())
      91. {
      92.     File runtimeClassesJar = new File(Utils.getSDKLibDir(), "android/lib/runtimeClasses.jar");
      93.     if (!runtimeClassesJar.exists())
      94.         throw new SDKDamagedException(runtimeClassesJar.getCanonicalPath());
      95.     dexCommand.add(runtimeClassesJar.getAbsolutePath());
      96. }

      97. //如果有ANE 则 加入FlashRuntimeExtensions.jar
      98. //加入ANE编写合计后的jar文件
      99. //PS:正因为这里加入了,所以编写ANE合计jar的时候
      100. //不需要合计FlashRuntimeExtensions.jar
      101. int numberOfExtensions = this.m_extensionsJars == null ? 0 : this.m_extensionsJars.length;
      102. if (numberOfExtensions > 0)
      103. {
      104.     dexCommand.add(flashRuntimeExtensionsJarPath);
      105.     for (int j = 0; j < numberOfExtensions; j++)
      106.     {
      107.         dexCommand.add(this.m_extensionsJars[j].getCanonicalPath());
      108.     }
      109. }

      110. //制定输出错误信息的字符串
      111. String dxOutputString = null;
      112. try {
      113.     ProcessBuilder pb = new ProcessBuilder(dexCommand);

      114.     Map env = pb.environment();

      115.     Process p = pb.start();
      116.     ByteArrayOutputStream dxOutput = new ByteArrayOutputStream();
      117.     new Utils.OutputEater(p.getErrorStream(), dxOutput).start();
      118.     new Utils.OutputEater(p.getInputStream()).start();
      119.     p.waitFor();
      120.     if (p.exitValue() != 0)
      121.         dxOutputString = new String(dxOutput.toByteArray(), "UTF-8");
      122. }
      123. catch (Exception e)
      124. {
      125.     throw new IOException("Unable to run dx");
      126. }
      127. //dx tool failed!
      128. //dx tool failed!
      129. //大家在打包APK发生错误的时候都应该看过这个错误信息弹出框.
      130. if (dxOutputString != null)
      131. {
      132.     throw new ADTException("dx tool failed:" + dxOutputString.toString(), 17);
      133. }
      复制代码

    • 分析代码后得出的完整命令如下
    1. //调用java执行dx.jar
    2. java
    3. //设定内存限制 举个例子 如下
    4. -Xmx512M -Xmz256M
    5. //调用 dx.jar
    6. -jar dx.jar
    7. //编译dex文件选项
    8. --dex
    9. //指定编译完成后的文件输出
    10. --outpath=D:/out/outdex.dex
    11. //启动类的模版类
    12. AppEntry_release.jar
    13. //资源ID所在的类 就是R.java(R.class文件)
    14. resource.jar
    15. //运行时类
    16. android/lib/runtimeClasses.jar
    17. //下面的ANE类库
    18. FlashRuntimeExtensions.jar
    19. [add ane is jar ]
    复制代码
    到现在,应该对整个编译源码过程有了大致的了解.
    执行完这个函数后 会生成一个dex文件 用于下一步:打包APK




    本文来自:http://shadowkong.com/archives/1460


    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    51788
    钢镚
    1422

    开源英雄守望者

     楼主| 发表于 2015-1-19 11:06:38 | 显示全部楼层
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2019-11-18 11:39 , Processed in 0.044405 second(s), 30 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表