Android实例仿真之二

目录

三 从无入手

第一阶段

第二阶段

第三阶段

第四阶段

第五阶段

第六阶段

第七阶段

八 举两个典型例子:

九 逆向工程


三 从无入手

   这节标题叫从无入手,什么意思呢?如果没有Android这个实例存在,你要做一个类似Android的东西,该怎么做?思考从这里开始。

   很多时候,我们的学习模式是反推模式。怎么讲呢,有些东西,有人先搞出来了,然后积累了很多经验,这些经验就成为后继者学习的内容。比如说,活字印刷术,为什么要弄字模,因为字模可以复用,提高效率。进一步的,可能会有字模为什么用这种材料,印刷为什么用这种纸等等。就像十万个为什么,当我们从为什么中得到这样做的好处后,我们就学习到很多有用的知识了。但实际上,现代的研究,都是主动式的。从以前经验总结提炼模式进化到先进行理论分析,得到可行性后,再指导实践研究,解决具体技术问题。这个过程,不仅是主动式的,而且也是正推模式的。比如要做一个产品,会进行需求分析,方案设计,之后才进行实施。如果产品取得了成功,其他人也想搞这类产品,那么他就会分析你的产品,这时候就进入了反推模式(一般也叫逆向工程)。他会思考,你为什么这样做,有什么好处。这虽然是一种比较快速的切入手段,但未必是快速成长之路,因为这种模式,一定程度上限制了我们的思考范围和深度。而且,部分在正推模式下未必是那么显而易见的信息,在反推中,就可能变成自然而然的了,这时候,就出现了信息的消失或者隐藏。举个不算太恰当的例子,假设一个机械计算器被设计为支持加法和乘法运算,当我们拆解这个计算器发现其内部有加法和乘法模块时,一定不会觉得有啥特别。但是,如果进一步的,发现乘法模块是由加法模块实现的时,可能会有那么一点点意想不到。总的来讲,这种反推模式,容易出现模块之间的有机关联性被割裂开,从而在系统层面的整体把握上,出现欠缺。再举个浅显的例子,我们都知道,上学做题时,自己思考出答案跟把答案看明白,是有很大的差别的。

   前面说了这么多,跟我们后面要继续展开的内容,有什么关系呢?看完下面的内容,大家就明白了。

   一直以来,我们学习Android的方式,都是反推模式。在学习过程中,有一天发现系统是这样设计的,可能得到的反馈就是“哦,原来如此”;有一天发现系统包含这些模块,可能得到的反馈是“嗯,是应该这样设计”。其实,这个过程,我们已经放弃了很多主动思考的机会,而是把更多的时间放到了思考答案到底有没有道理、对不对上去了。所以这里,我们尝试从正向来“分析”一下Android系统,看看会有什么不同的收获。

   秉着先设计后实现的理念,如果给我们一个构建Android系统的机会,那我们应该先考虑的是要做什么,然后再考虑怎么做,这个顺序才是正确的。对于一个复杂系统的设计,顺手就可能拎出来几条放之四海而皆准的要求或特性。比如:

   1 能够简化应用开发,满足工业化、商业化、标准化的要求。这是基础要求。

   2 要开放共享,共建共治。

   3 要灵活,有很强的适应性、扩展性、维护性。

   4 要高性能高可靠。

   5 要有竞争力,适应面广,有市场。

   6 要能可持续性发展,最好有大公司或者公司联盟背书。

   7 上面的都比较虚,如果有现成实际可运行的演示产品或成果就更好了。这一步实现虚转实,这一点很重要。iPhone的惊艳亮相、AlphaGo的一战成名、ChatGPT的量变到质变跃迁,无不为产业界注入了强心剂。

   8 能够重复利用现有的成果,那成功的可能性就更大了。

   9 当然,如果再包装一番,显得与众不同,显得同时具备先进理念和可玩性,那就更吸引开发者和用户了。

   有了上面的安9条,然后我们再来看,该如何设计才能实现上面的要求。

   看未来,最好的方法就是回看历史。这是唯物主义告诉我们的方法论。不过这一点显得太哲学化,缺乏实践方面的具体指导价值。我们还是从现有的软件系统来看,该如何做。下面将这个思考过程整理成七个阶段,通过框图分别展示。不过,为了让内容更加聚焦,我们会忽略比较多的细节。

第一阶段

   标准分层开发模式

第二阶段

   多应用模式,应用不分业务、服务、资源

第三阶段

   多应用模式,应用分业务、服务、资源,但没有统一规划

第四阶段

   多应用模式,应用分业务、服务、资源,服务和资源有统一规划

第五阶段

   多应用模式,应用分业务、服务、资源,服务和资源进一步独立规划

第六阶段

   多应用模式,部分业务和服务或者资源中,为了共享、复用逻辑或数据或流程,采用了模块化方式,也认为是标准构件的雏形。此时的典型特点是不对外开放,内部较为宽松模式下的实现。

第七阶段

   多应用模式,业务、服务和资源统一使用大框架进行分层管理。应用中嵌入标准构件。典型的特点是对外开放,标准化,实现考虑东西较多。

   通过上面的演化步骤,从历史角度来看,我们隐约也能感觉到那种从手工农耕到机器标准化作业的感觉。

   看来任何时候,向标准化、工业化目标看齐,都不会错的。

   下面,基于上面九条要求,从静态和动态两个方面来看具体实现时该如何入手。

八 举两个典型例子:

   其一,应用内,周期管理

   上图展示了这样一个可能的理想化方案。APP1和APP2,当然可能还有更多的APP跟框架主代码通过编译,结合在一起。系统加载包含编译结果的程序文件时,会通过写时拷贝,复用父进程已经构建的内置资源。父进程的内置资源是继承在父进程的父进程。不断的回溯,最开的进程只包含少量资源,运行过程中逐步分化出子进程,子进程加载更多的资源,最终构建起完整资源的应用启动进程。操作系统从该完整进程分裂出各个具体的应用进程,自然,应用进程就具备了父进程包含的资源。等到运行时,系统将消息推送给应用进程,应用进程就按照框架设计的周期规格,本分的运行了。

   其二,应用内或者应用间,远程过程调用。可以在线程间,或者进程间实现。应用内,主要是线程间的通信,方便消息的处理;应用间,主要是进程间的通信,方面进行服务的获取和使用。

   对于进程间的模式,框架同样提供了接口,并在接口实现中定义了远程过程调用的方法。服务端则真正定义了接口实现,并处理远端过来的调用,将结果返回给远端调用者。服务端在实现接口本身的要求时,可能需要操作系统和驱动的支持。远程过程调用作为框架代码,在应用端和服务端有各自的模板实现。开发者可以通过专门的脚步语言描述调用方法和参数,这通常称为接口描述语言。之后,有专门的工具将其翻译为可嵌入框架的代码。公用的部分(外部包装)由工具实现,用户只需要实现逻辑本身要求的代码即可。

   编译时,框架和相关代码一起编译,形成一个完整的代码段。运行时,为了提高效率,远程过程调用会进入到内核空间执行,这样就可以完成跨进程的高效内存数据传递。

   通过上面两个例子,我们对框架干什么及如何干,应该有个隐隐约约的感觉了吧。这些内容,跟之前的博文传递的思想是一致的(软件架构及几种典型框架_龙赤子的博客-CSDN博客_软件架构)。

   具体看Android系统的实现方式之前,我们先简单看一个实践层面的验证。这需要对Android应用进行一个简单的逆向工程。所以,这个过程,我们也就顺便简单介绍一下Android应用的逆向方法。

九 逆向工程

   基本的逆向工具有 dex2jar和jd-gui。具体方法如下:

   首先将Android应用的安装包apk文件重命名为zip文件,并将其解压到文件夹。

其次使用dex2jar将文件夹中的class.dex文件反编译为jar文件。Dex是一种字节码格式,class.dex就是Android应用代码编译后准备交给虚拟机的“类二进制”文件。

最后使用jd-gui工具查看jar文件中包含的反编译后的Java代码。

   但是,使用上面的工具有个问题:有些应用apk包做了加固处理,逆向转jar时可能报错,无法正常处理。还有一个,就是有些应用apk可能存在多个class.dex文件。这主要是Android早期虚拟机的限制导致。

   使用dex2jar最新2.1版本(2.0不可以)可以处理一些加固措施,比如转jar的报错问题,但是无法处理多个class.dex文件的情况。此时,可以使用jadx工具。直接从github下载编译好的支持gui且带jre版本的jadx-gui。启动工具,在图形界面中拖入要分析的apk,可一步到位完成反编译及Java类展示,方便快捷。

   简单工程,如下图所示:

   老工具逆向会报错的应用,如下图所示:

   看着有些差异。

   包含多class.dex文件的情况,如下图所示:

   从其中,我们可以看到,无论是那种情况,除了我们自己的代码外,还有第三方的代码以及安卓系统的代码。这基本验证了框架代码会和我们的代码一起揉到应用中。

   有了上面的基础,下面让我们从大的方面来看看Android内部具体是怎么做的。

猜你喜欢

转载自blog.csdn.net/wwwyue1985/article/details/129114993
今日推荐