Android-FixBug热修复框架的使用及源码分析(不发版修复bug)

前面几篇博文已经介绍了2种热修复框架的使用及源码分析,AndFix兼容性比较好,而Dexposed Art处于Beta版。

AndFix和Dexposed都是阿里的开源项目。 
Alibaba-AndFix Bug热修复框架的使用 
Alibaba-AndFix Bug热修复框架原理及源码解析 
Alibaba-Dexposed框架在线热补丁修复的使用 
Alibaba-Dexposed Bug框架原理及源码解析

今天主要介绍的框架是根据腾讯的博客使用ClassLoader写的热修复框架。 
腾讯博客:【新技能get】让App像Web一样发布新版本

首先,看需要修复的类部分:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">package</span> cn.coolspan.open.fixbug;

<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.io.File;

<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.app.Activity;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.os.Bundle;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.os.Environment;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.util.Log;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.view.View;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.view.View.OnClickListener;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.widget.Toast;

<span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
 * MainActivity 2015-12-22 下午10:30:57
 *
 *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @author</span> 乔晓松 965266509@qq.com
 */</span>
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">class</span> <span class="hljs-title" style="color:#66066;box-sizing: border-box;">MainActivity</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">extends</span> <span class="hljs-title" style="color:#66066;box-sizing: border-box;">Activity</span> {</span>

    <span class="hljs-annotation" style="color:#9b859d;box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(Bundle savedInstanceState) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button1).setOnClickListener(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> OnClickListener() {

            <span class="hljs-annotation" style="color:#9b859d;box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View view) {
                MyApplication myApplication = (MyApplication) getApplication();
                File patch = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(
                        Environment.getExternalStorageDirectory(), <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"patch.jar"</span>);
                Log.e(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"file:"</span>, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">""</span> + patch.exists());
                myApplication.fixBugManage.addPatch(patch.getAbsolutePath());
            }
        });
        findViewById(R.id.button2).setOnClickListener(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> OnClickListener() {

            <span class="hljs-annotation" style="color:#9b859d;box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View view) {
            <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//修复此位置的bug</span>
                Toast.makeText(MainActivity.<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"...bug..."</span>,
                        Toast.LENGTH_SHORT).show();
            }
        });
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li></ul>

以上是手机上安装的apk存在bug的位置。

接下,是修复完成Bug后的类:

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">...</span><span class="hljs-attribute" style="box-sizing: border-box;">...</span>
<span class="hljs-attribute" style="box-sizing: border-box;">...</span><span class="hljs-attribute" style="box-sizing: border-box;">...</span>
findViewById(R<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>id<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>button2)<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>setOnClickListener(<span class="hljs-literal" style="color:#06666;box-sizing: border-box;">new</span> OnClickListener() {

            @Override
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">void</span> onClick(View view) {
                Toast<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>makeText(MainActivity<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>this, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"fix...bug..."</span>,
                        Toast<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>LENGTH_SHORT)<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>show();
            }
        });
<span class="hljs-attribute" style="box-sizing: border-box;">...</span><span class="hljs-attribute" style="box-sizing: border-box;">...</span>
<span class="hljs-attribute" style="box-sizing: border-box;">...</span><span class="hljs-attribute" style="box-sizing: border-box;">...</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>

修复好了,build工程(工具也会自动build),把java编译成class文件。

由于我使用debug模式调试安装的apk,所以我build完成后找的也是debug下的class文件,如下: 
这里写图片描述 
红色框标注的部分就是MainActivity build完成后生成class文件,如果你想问我怎么是三个class文件,原因是:onCreate中有2个注册的点击时间监听器,每个监听器都生成了一个新的class文件。

把相关修复bug的类的class文件复制到一个文件下(fixbugdex),当前我也保存了class所在的包。如下: 
这里写图片描述

以下,拷贝方式不可取: 
如果在工具中看class文件,效果如下:

这里写图片描述

这里看到的仅有一个MainActivity.class,切记,这是工具为了方便你查看class文件,显示上做了处理。不能从此位置单独一个个class文件拷贝,例如从此位置单独拷贝出MainActivity.class,这个class就不是完成的类了,文件内容如下: 
这里写图片描述

所以此方式不可取,当然可以直接拷贝整个包。 
然后cmd到刚才的fixbugdex文件 
这里写图片描述 
然后执行命令 jar cvf fixbug.jar cn/* 
这条命令就是把cn下的所有文件打包到fixbug.jar文件中 
这里写图片描述 
执行完成后: 
这里写图片描述 
查看fixbug.jar内容: 
这里写图片描述

接下,需要把jar文件转换成dex文件: 
工具:dx

下载工具并解压到AndroidSdk–>platform-tools目录 
这里写图片描述 
同时,也可以把fixbug.jar文件拷贝到AndroidSdk–>platform-tools目录,然后你也可以使用绝对路径.

cmd到AndroidSdk–>platform-tools目录下执行命令:

<code class="hljs brainfuck has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">dx</span> <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">-</span><span class="hljs-literal" style="color:#06666;box-sizing: border-box;">-</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">dex</span> <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">-</span><span class="hljs-literal" style="color:#06666;box-sizing: border-box;">-</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">output</span> <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">patch</span><span class="hljs-string" style="color:#0880;box-sizing: border-box;">.</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">jar</span> <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">fixbug</span><span class="hljs-string" style="color:#0880;box-sizing: border-box;">.</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">jar</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

注:–output 后面可以接绝对路径。 
这里写图片描述

执行完成后的结果: 
这里写图片描述

查看一下patch.jar文件的内容: 
这里写图片描述

打开应用执行Toast按钮: 
我为了测试方便,把patch.jar文件放到了sdcard根目录中,当然也可以选择网上下载的方式,其实都是一样的。

启动后效果如下: 
这里写图片描述

然后,点击加载补丁文件,并推出应用重新进入,并点击Toast按钮: 
这里写图片描述

到此,bug已经被修复完成。

Api接口介绍:

首先,把FixBugManage.java文件引入到你的项目中

首先,在自定义Application中初始化: 
init(versionCode); 
当versionCode与之前的versionCode不同,会自动清除掉之前addPatch所有的补丁文件 
当versionCode与之前的versionCode相同,会自动加载之前addPatch所有的补丁文件

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">package</span> cn.coolspan.open.fixbug;

<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.app.Application;

<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">class</span> <span class="hljs-title" style="color:#66066;box-sizing: border-box;">MyApplication</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">extends</span> <span class="hljs-title" style="color:#66066;box-sizing: border-box;">Application</span> {</span>

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> FixBugManage fixBugManage;

    <span class="hljs-annotation" style="color:#9b859d;box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>() {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">super</span>.onCreate();
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.fixBugManage = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> FixBugManage(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>);
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.fixBugManage.init(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"1.0"</span>);
    }
}
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

添加新补丁文件接口: 
addPatch(patchPath);

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> MyApplication myApplication = (MyApplication) getApplication()<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">;</span>
                File patch = new File(
                        Environment<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.getExternalStorageDirectory</span>(), <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"patch.jar"</span>)<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">;</span>
                myApplication<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.fixBugManage</span><span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.addPatch</span>(patch<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.getAbsolutePath</span>())<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

清除所有补丁文件的接口:

<code class="hljs dos has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">removeAllPatch();</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

到此接口已介绍完。

中途遇到的坑:

执行jar cvf fixbug.jar cn/* 
异常:bad class file magic (cafebabe) or version (0033.0000) 
解决方法:在build.gradle中jdk的版本修改为1.6

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> compileOptions {
        sourceCompatibility JavaVersion<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.VERSION</span>_1_6
        targetCompatibility JavaVersion<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.VERSION</span>_1_6
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

FixBugManage源码分析:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">package</span> cn.coolspan.open.fixbug;

<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.io.BufferedInputStream;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.io.BufferedOutputStream;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.io.File;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.io.FileInputStream;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.io.FileOutputStream;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.io.IOException;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.io.OutputStream;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.lang.reflect.Array;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.lang.reflect.Field;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.math.BigInteger;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> java.security.MessageDigest;

<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> dalvik.system.DexClassLoader;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> dalvik.system.PathClassLoader;

<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.content.Context;
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">import</span> android.content.SharedPreferences;

<span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
 * FixBugManage 2015-12-22 下午9:59:28
 *
 *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @author</span> 乔晓松 965266509@qq.com
 */</span>
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">class</span> <span class="hljs-title" style="color:#66066;box-sizing: border-box;">FixBugManage</span> {</span>

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> Context context;

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> BUF_SIZE = <span class="hljs-number" style="color:#06666;box-sizing: border-box;">2048</span>;

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> File patchs;
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> File patchsOptFile;

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">FixBugManage</span>(Context context) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.context = context;
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.patchs = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.context.getFilesDir(), <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"patchs"</span>);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 存放补丁文件</span>
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.patchsOptFile = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.context.getFilesDir(), <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"patchsopt"</span>);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 存放预处理补丁文件压缩处理后的dex文件</span>
    }

    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
     * 初始化版本号
     *
     *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @param</span> versionCode
     */</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">init</span>(String versionCode) {
        SharedPreferences sharedPreferences = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.context
                .getSharedPreferences(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"fixbug"</span>, Context.MODE_PRIVATE);
        String oldVersionCode = sharedPreferences
                .getString(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"versionCode"</span>, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>);
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (oldVersionCode == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>
                || !oldVersionCode.equalsIgnoreCase(versionCode)) {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.initPatchsDir();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 初始化补丁文件目录</span>
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.clearPaths();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 清楚所有的补丁文件</span>
            sharedPreferences.edit().clear().putString(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"versionCode"</span>, versionCode)
                    .commit();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 存储版本号</span>
        } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.loadPatchs();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 加载已经添加的补丁文件(.jar)</span>
        }
    }

    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
     * 读取补丁文件夹并加载
     */</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">loadPatchs</span>() {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (patchs.exists() && patchs.isDirectory()) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 判断文件是否存在并判断是否是文件夹</span>
            File patchFiles[] = patchs.listFiles();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 获取文件夹下的所有的文件</span>
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>; i < patchFiles.length; i++) {
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (patchFiles[i].getName().lastIndexOf(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">".jar"</span>) == patchFiles[i]
                        .getName().length() - <span class="hljs-number" style="color:#06666;box-sizing: border-box;">4</span>) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 仅处理.jar文件</span>
                    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.loadPatch(patchFiles[i].getAbsolutePath());<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 加载jar文件</span>
                }
            }
        } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.initPatchsDir();
        }
    }

    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
     * 加载单个补丁文件
     *
     *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @param</span> patchPath
     */</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">loadPatch</span>(String patchPath) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {
            injectDexAtFirst(patchPath, patchsOptFile.getAbsolutePath());<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 读取jar文件中dex内容</span>
        } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (Exception e) {
            e.printStackTrace();
        }
    }

    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
     * patch所在文件目录
     *
     *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @param</span> patchPath
     */</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">addPatch</span>(String patchPath) {
        File inFile = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(patchPath);
        File outFile = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(patchs, inFile.getName());
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.copyFile(outFile, inFile);
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.loadPatch(patchPath);
    }

    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
     * 移除所有的patch文件
     */</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">removeAllPatch</span>() {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.clearPaths();
    }

    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
     * 清除所有的补丁文件
     */</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">clearPaths</span>() {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (patchs.exists() && patchs.isDirectory()) {
            File patchFiles[] = patchs.listFiles();
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>; i < patchFiles.length; i++) {
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (patchFiles[i].getName().lastIndexOf(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">".jar"</span>) == patchFiles[i]
                        .getName().length() - <span class="hljs-number" style="color:#06666;box-sizing: border-box;">4</span>) {
                    patchFiles[i].delete();
                }
            }
        }
    }

    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
     * 初始化存放补丁的文件目录
     */</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">initPatchsDir</span>() {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.patchs.exists()) {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.patchs.mkdirs();
        }
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.patchsOptFile.exists()) {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>.patchsOptFile.mkdirs();
        }
    }

    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
     * 复制文件从inFile到outFile
     *
     *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @param</span> outFile
     *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @param</span> inFile
     *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @return</span>
     */</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">copyFile</span>(File outFile, File inFile) {
        BufferedInputStream bis = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>;
        OutputStream dexWriter = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>;
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {
            MessageDigest digests = MessageDigest.getInstance(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"MD5"</span>);

            bis = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> BufferedInputStream(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> FileInputStream(inFile));
            dexWriter = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> BufferedOutputStream(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> FileOutputStream(outFile));
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">byte</span>[] buf = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">byte</span>[BUF_SIZE];
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> len;
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">while</span> ((len = bis.read(buf, <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>, BUF_SIZE)) > <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>) {
                digests.update(buf, <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>, len);
                dexWriter.write(buf, <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>, len);
            }
            dexWriter.close();
            bis.close();
            BigInteger bi = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> BigInteger(<span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>, digests.digest());
            String result = bi.toString(<span class="hljs-number" style="color:#06666;box-sizing: border-box;">16</span>);

            File toFile = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(outFile.getParentFile(), result + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">".jar"</span>);
            outFile.renameTo(toFile);
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>;
        } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (Exception e) {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (dexWriter != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {
                    dexWriter.close();
                } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (bis != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {
                    bis.close();
                } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;
        }
    }

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">injectDexAtFirst</span>(String dexPath, String defaultDexOptPath)
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> NoSuchFieldException, IllegalAccessException,
            ClassNotFoundException {
        DexClassLoader dexClassLoader = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> DexClassLoader(dexPath,
                defaultDexOptPath, dexPath, getPathClassLoader());<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 把dexPath文件补丁处理后放入到defaultDexOptPath目录中</span>
        Object baseDexElements = getDexElements(getPathList(getPathClassLoader()));<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 获取当面应用Dex的内容</span>
        Object newDexElements = getDexElements(getPathList(dexClassLoader));<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 获取补丁文件Dex的内容</span>
        Object allDexElements = combineArray(newDexElements, baseDexElements);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 把当前apk的dex和补丁文件的dex进行合并</span>
        Object pathList = getPathList(getPathClassLoader());<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 获取当前的patchList对象</span>
        setField(pathList, pathList.getClass(), <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dexElements"</span>, allDexElements);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 利用反射设置对象的值</span>
    }

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> PathClassLoader <span class="hljs-title" style="box-sizing: border-box;">getPathClassLoader</span>() {
        PathClassLoader pathClassLoader = (PathClassLoader) FixBugManage.class
                .getClassLoader();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 获取类加载器</span>
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> pathClassLoader;
    }

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> Object <span class="hljs-title" style="box-sizing: border-box;">getDexElements</span>(Object paramObject)
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> IllegalArgumentException, NoSuchFieldException,
            IllegalAccessException {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> getField(paramObject, paramObject.getClass(), <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dexElements"</span>);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 利用反射获取到dexElements属性</span>
    }

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> Object <span class="hljs-title" style="box-sizing: border-box;">getPathList</span>(Object baseDexClassLoader)
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> IllegalArgumentException, NoSuchFieldException,
            IllegalAccessException, ClassNotFoundException {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> getField(baseDexClassLoader,
                Class.forName(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dalvik.system.BaseDexClassLoader"</span>), <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"pathList"</span>);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 利用反射获取到pathList属性</span>
    }

    <span class="hljs-javadoc" style="color:#8800;box-sizing: border-box;">/**
     * 此方法是合并2个数组,把补丁dex中的内容放到数组最前,达到修复bug的目的
     *
     *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @param</span> firstArray
     *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @param</span> secondArray
     *<span class="hljs-javadoctag" style="color:#66066;box-sizing: border-box;"> @return</span>
     */</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> Object <span class="hljs-title" style="box-sizing: border-box;">combineArray</span>(Object firstArray, Object secondArray) {
        Class<?> localClass = firstArray.getClass().getComponentType();
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> firstArrayLength = Array.getLength(firstArray);
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> allLength = firstArrayLength + Array.getLength(secondArray);
        Object result = Array.newInstance(localClass, allLength);
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> k = <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>; k < allLength; ++k) {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (k < firstArrayLength) {
                Array.set(result, k, Array.get(firstArray, k));
            } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {
                Array.set(result, k,
                        Array.get(secondArray, k - firstArrayLength));
            }
        }
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> result;
    }

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> Object <span class="hljs-title" style="box-sizing: border-box;">getField</span>(Object obj, Class<?> cl, String field)
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException {
        Field localField = cl.getDeclaredField(field);
        localField.setAccessible(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 强制反射</span>
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> localField.get(obj);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 获取值</span>
    }

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setField</span>(Object obj, Class<?> cl, String field,
                                Object value) <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> NoSuchFieldException,
            IllegalArgumentException, IllegalAccessException {
        Field localField = cl.getDeclaredField(field);
        localField.setAccessible(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 强制反射</span>
        localField.set(obj, value);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 设置值</span>
    }
}
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li><li style="box-sizing: border-box; padding: 0px 5px;">177</li><li style="box-sizing: border-box; padding: 0px 5px;">178</li><li style="box-sizing: border-box; padding: 0px 5px;">179</li><li style="box-sizing: border-box; padding: 0px 5px;">180</li><li style="box-sizing: border-box; padding: 0px 5px;">181</li><li style="box-sizing: border-box; padding: 0px 5px;">182</li><li style="box-sizing: border-box; padding: 0px 5px;">183</li><li style="box-sizing: border-box; padding: 0px 5px;">184</li><li style="box-sizing: border-box; padding: 0px 5px;">185</li><li style="box-sizing: border-box; padding: 0px 5px;">186</li><li style="box-sizing: border-box; padding: 0px 5px;">187</li><li style="box-sizing: border-box; padding: 0px 5px;">188</li><li style="box-sizing: border-box; padding: 0px 5px;">189</li><li style="box-sizing: border-box; padding: 0px 5px;">190</li><li style="box-sizing: border-box; padding: 0px 5px;">191</li><li style="box-sizing: border-box; padding: 0px 5px;">192</li><li style="box-sizing: border-box; padding: 0px 5px;">193</li><li style="box-sizing: border-box; padding: 0px 5px;">194</li><li style="box-sizing: border-box; padding: 0px 5px;">195</li><li style="box-sizing: border-box; padding: 0px 5px;">196</li><li style="box-sizing: border-box; padding: 0px 5px;">197</li><li style="box-sizing: border-box; padding: 0px 5px;">198</li><li style="box-sizing: border-box; padding: 0px 5px;">199</li><li style="box-sizing: border-box; padding: 0px 5px;">200</li><li style="box-sizing: border-box; padding: 0px 5px;">201</li><li style="box-sizing: border-box; padding: 0px 5px;">202</li><li style="box-sizing: border-box; padding: 0px 5px;">203</li><li style="box-sizing: border-box; padding: 0px 5px;">204</li><li style="box-sizing: border-box; padding: 0px 5px;">205</li><li style="box-sizing: border-box; padding: 0px 5px;">206</li><li style="box-sizing: border-box; padding: 0px 5px;">207</li><li style="box-sizing: border-box; padding: 0px 5px;">208</li><li style="box-sizing: border-box; padding: 0px 5px;">209</li><li style="box-sizing: border-box; padding: 0px 5px;">210</li><li style="box-sizing: border-box; padding: 0px 5px;">211</li><li style="box-sizing: border-box; padding: 0px 5px;">212</li><li style="box-sizing: border-box; padding: 0px 5px;">213</li><li style="box-sizing: border-box; padding: 0px 5px;">214</li><li style="box-sizing: border-box; padding: 0px 5px;">215</li><li style="box-sizing: border-box; padding: 0px 5px;">216</li><li style="box-sizing: border-box; padding: 0px 5px;">217</li><li style="box-sizing: border-box; padding: 0px 5px;">218</li><li style="box-sizing: border-box; padding: 0px 5px;">219</li><li style="box-sizing: border-box; padding: 0px 5px;">220</li><li style="box-sizing: border-box; padding: 0px 5px;">221</li><li style="box-sizing: border-box; padding: 0px 5px;">222</li><li style="box-sizing: border-box; padding: 0px 5px;">223</li><li style="box-sizing: border-box; padding: 0px 5px;">224</li><li style="box-sizing: border-box; padding: 0px 5px;">225</li><li style="box-sizing: border-box; padding: 0px 5px;">226</li><li style="box-sizing: border-box; padding: 0px 5px;">227</li><li style="box-sizing: border-box; padding: 0px 5px;">228</li><li style="box-sizing: border-box; padding: 0px 5px;">229</li><li style="box-sizing: border-box; padding: 0px 5px;">230</li><li style="box-sizing: border-box; padding: 0px 5px;">231</li><li style="box-sizing: border-box; padding: 0px 5px;">232</li><li style="box-sizing: border-box; padding: 0px 5px;">233</li><li style="box-sizing: border-box; padding: 0px 5px;">234</li><li style="box-sizing: border-box; padding: 0px 5px;">235</li><li style="box-sizing: border-box; padding: 0px 5px;">236</li><li style="box-sizing: border-box; padding: 0px 5px;">237</li><li style="box-sizing: border-box; padding: 0px 5px;">238</li><li style="box-sizing: border-box; padding: 0px 5px;">239</li><li style="box-sizing: border-box; padding: 0px 5px;">240</li><li style="box-sizing: border-box; padding: 0px 5px;">241</li><li style="box-sizing: border-box; padding: 0px 5px;">242</li><li style="box-sizing: border-box; padding: 0px 5px;">243</li><li style="box-sizing: border-box; padding: 0px 5px;">244</li><li style="box-sizing: border-box; padding: 0px 5px;">245</li><li style="box-sizing: border-box; padding: 0px 5px;">246</li><li style="box-sizing: border-box; padding: 0px 5px;">247</li><li style="box-sizing: border-box; padding: 0px 5px;">248</li><li style="box-sizing: border-box; padding: 0px 5px;">249</li><li style="box-sizing: border-box; padding: 0px 5px;">250</li><li style="box-sizing: border-box; padding: 0px 5px;">251</li><li style="box-sizing: border-box; padding: 0px 5px;">252</li><li style="box-sizing: border-box; padding: 0px 5px;">253</li><li style="box-sizing: border-box; padding: 0px 5px;">254</li><li style="box-sizing: border-box; padding: 0px 5px;">255</li><li style="box-sizing: border-box; padding: 0px 5px;">256</li></ul>

如有bug或者不足,可以即时告知我,我会即时修改。

原文地址: http://blog.csdn.net/qxs965266509/article/details/50390325

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值