可门级数码相机剁手指南

  前言:每当上同一篇博文《小白为能够看懂的插件化DroidPlugin原理(一)–
动态代理》受详尽介绍了
DroidPlugin
原理中涉及到之动态代理模式,看罢上篇博文后若尽管见面发觉原动态代理真的非常简单,只不过就是是实现一个
InvocationHandler 接口重写一下 invoke 方法而已。不错,其实过多好像 high
level
的技艺还连从未想象着之那晦涩难了解,只要你愿意下定狠心去探听她,去认识她,去读她若虽见面发觉,原来还是足以学得亮的。本篇博文将介绍
DroidPlugin 框架中时时因此到的另外两只知识点–反射机制和Hook技术。

李斯特 ·从一个枕头到世界

于上个世纪出游至他太空的旅游者1号带的那张“地球名片”的光盘达,带有一百基本上布置显得人类风貌的像。利用相机这种“自动再现世界的景装置”。人们逐步摆脱传统的画笔和颜色,步入了“以光线绘图”的一世。

  本系列文章的代码都上传至github,下载地址:https://github.com/lgliuwei/DroidPluginStudy 本篇文章对应之代码在
com.liuwei.proxy_hook.reflect
和 com.liuwei.proxy_hook.hook.simplehook 包内。

“地球名片”中之同布置照片

这些为称之为“照片”的事物,当时早就当人类历史及设有了一段时间。
利用小孔成像原理的针孔照相机,也叫暗箱,就是照相机的本来面目。

继人们又下银盐效应,让照相之青山绿水可以透过冲洗停留在介质上叫保存下来。唐麦库宁说,他“尊敬底片就像尊敬大海,因为它比自己好得最多矣。”

若果打字之于书写,MP3的被唱片机,人类尚未休止了步伐。暗房、冲洗、胶片这些重大词在历史上褪去颜色后,我们到了数码相机盛行之还要一个秋。感光元件CCD/CMOS
取代了胶片的意,直接拿单纯信号转化为电信号储存起来。

前途定还会出啊又神奇的装置出现,也许有同一天相机几乎等同于人眼。

不过今天咱们只聊数码相机。我不敢说马上是最最好的时日,但迅即一定非是极酷的一代;镜头面前或拥有各种东西,但绝对免是一无所有。

相同、反射机制

▎李斯特的清单

Canon EOS 750D 单反套机

Canon EOS 760D 单反套机

Nikon D5500 单反套机

Nikon D5300 单反套机

Sony A6000 微单相机

Fujifilm X-M1 微单相机

Fujifilm X-T10 微单相机

SIGMA/适马 50mm f/1.4镜头

SIGMA/适马 35mm F1.4 DG HSM 镜头

Tamron/腾龙 AF18-200mm F/3.5-6.3 镜头



  1、反射是什么?

拿起相机之前

着见相同摆放令人心动的照相创作时,大多数总人口见面问即是用什么相机冲击的,但是遇到同样摆放难看的著述之时候,大多数丁会面咨询,这是何许人也拍的。

一经告诉你这是手机拍出来的,敢相信啊?

立刻张《雪地上之旅行者》正是同各类名叫吧JULIO LUCAS 的人拍摄,获得2014 IPPA
iphone 摄影大赛冠军之照创作。

要是拍,你仅仅待肉眼之外至少一华装备,它可以是单反、卡片机或者手机;若要“好好拍”,就还索要一发“与具体世界随时谈恋爱的良心”。

  JAVA反射机制是在运作状态被,对于自由一个好像,都能够清楚之类似的享有属性与措施;对于随意一个目标,都能调用它的任意方法及性能;这种动态获取信息以及动态调用对象方法的效应称为java语言的反射机制。

❶ 好之照相创作在什么?

习以为常来讲,摄影作品的质被以下这些元素的影响:

画质:画面是不是清楚,有多详细的讲述能力。(像素数)

构图:同一一个东西,不同之相距和角度可传递不一致的思量。(焦距)

光线:既被誉为“用强光构图”,对光泽的把握那个要。主要反映为对上光量以及曝光度的操纵。(感光度、光圈和快门)

主题:各个一样摆设摄影创作还设发生凸起展现的始末。

  2、反射机制的打算:

❷ 当我们当座谈器材时,我们以议论什么?

暨购买别的任何事物一律,买相机同样看预算。“一分割价钱一样分货”这词话,十分适用于相机的选购。简单粗暴的游说:如果您就发平等维需求,在你的一定需求下购买最贵的,或是在你的预算内买最符合您需要(画质/功能多样性/外观……)的那款。

除却还需要了解一些周边而直接的参数:

焦距:焦距数值越小/大,能拍摄逾广/远的限,根据数值不同而分为广角映象、标准镜头、长焦镜头。

光圈:光圈的数值越小/大,光圈孔径越大/小,进光量越多/少,画面更是清楚/灰暗,景深(即针对好焦的界定)越浅/深。

感光度:ISO感光度越高/低,感光元件对光泽越敏感/不灵动,所拍照片更是明/灰暗,噪点也就越是多/少。

快门:快门速度越快/慢,光线通过日越短/长,画面更是暗/亮,越能够抓拍瞬间/表现过程。

全画幅/截幅:浅地说,全幅是跟135胶片一样大小的感光元件,截幅式相机便是把全画幅相机照中的部分,截一帧出来,相当给转换焦拉近。两者的分别一般也1.5倍增,全画幅机的画质也又精。

打听这些参数,不仅涉嫌到打相机,也涉及到今后摄影技巧的掌握。

  (1)反射可以当运转时判断任意一个目标所属之接近;

一个话题

生一样步就是准备下手设备,但这时脑海里出现了少数只打架的小不点儿,

“想玩摄影当然选单反啦,不仅机器专业,镜头群也增长…”

“可是我道特反好没,出门旅行、逛街按拍,我并无思坐在辣么重的火器啦。听说近年来出现了同样栽东西被微单?”

就就算是近些年纪念着手相机的人们面临的一个麻烦话题。选相机,单反还是微单?在开了片询问以及研讨后,我总发生了同布置图,大致对其做出比较。

当下只有是一个比简化的报表。实在对相机而言,不同品牌的例外系列产品,已经超过了这些直接对比的维度,有着各自不同的卖点。一些海舰款微单,已经好直达与中高端单反相媲美的水平,因此一定要显现“机”行事,根据自己之购入需求来对待得出结论。

  (2)反射可以当运行时组织任意一个类似的对象;

少种相机

优先来说单反,对于拍而言,单反本身的原则性就是是“专业性”,看重专业的镜头群配置和晋升能力,因此“入门级单反”在某种程度上实际是一个矛盾命题:如果想要耍摄影,入门级单反只能于及初阶学习与属的意;如果只是想拍,专业性能与单反的赛价位就会见带比较逊色的性价比。

而是依然如推荐的理是:无论是佳能还是尼康,即使在入门级产品及还开始侧重用户各地方的体验,有些还是于入门款上放了中高端机型的配备,让初阶摄影之空中更换得重新甚。对此升级能力及转移镜头吧,单反为愈加安定、专业,适合“可领单反略重之个子,以及想如果‘好好拍’的人流”。

C 家和N 家各推荐2款:

  (3)反射可以在运作时判断任意一个接近有的随意成员变量和章程;

❶ Canon EOS 750D/760D

之所以将有限独型号放在一起推荐,是盖马上是佳能今年同时推出的少数款款普及型单反相机。并让佳能官方称为相较于前代出品之“全面提升”。

Canon 750D
与前代出品650D/700D相比,在感光元件、图像处理器等地方都出一揽子的晋升,并参加wifi
功能
。同时出的Canon 760D
更是多了双双拨轮、肩屏和电子水平仪等较高档的特征,价格为于750D
更强一些。总之,750D 偏重日常使用,760D
在入门级领域又拥有专业性,可据实际要求选择。

  (4)反射可以于运作时调用任意一个接近的随意方法;

❷ Nikon D5500/D5300

暨佳能相对,尼康D5x00多元一直是入门级单反的优选。除了画质优秀,一些高端机才有的配置也吃放逐至可门款上,从D5100直至今天之D5500,不论是性质还是设计都更加发细腻。D5500机身仅重470g,比达一代D5300还要轻60g,也累了D5300
开始新增的wifi功能。Nikon D5500 广告被谓它是世界最为小最轻量的照相机。

小栗旬拿在的及时款相机便是Nikon D5500

假若手中一度发D5300级别的配备,则无建议提升。因为D5500相对前代出品的优势并无很显,比较强烈的变型是此处:

初参加的touchscreen即触控屏让操作更灵敏,D5500也成尼康家族中首款触控屏相机。对于习惯以智能手机的人们来说,这应当会成更易上手的等同栽办法。但万一预算不够,触摸屏这同样码职能对你而言没有那么重大的话,D5300也是一点一滴推荐的高性价比之选。

再来说微单,据说8月5哀号,Sony门店前排自了长队…….

来拘禁一样摆放图:

8月5日索尼正式发售全画幅微单A7R2,这款采用了高像素和五轴防抖等技能的晋级微单激起广大发烧友的古道热肠。图为Flickr网站的Camera
Ownership 数据图,可见到占据微单市场的几乎不行品牌,而索尼占有绝对分量。

微单的齐是微型可变换镜头式单镜头数码相机,这个词是索尼率先在中原登记之,取“微小机身,单反的用”之完全。尽管在索尼推出微单之前,几杀品牌还曾推出了看似机型,但会称呼吗“微单”的准及一味来索尼。这里不举行具体分,只笼统地管大部分这种无反光板和五棱镜的不过更换镜头相机号称微单相机。

奥林巴斯把微单定位成“摄影师的次高相机,普通人用来记录生活之家伙”。尽管微单还设有重重争辩,但技术之升华为微单逐渐变成众人置相机时之抉择之一。同才反一样,微单的不比价位决定了产品的性及布局,同系列产品价格更胜似,配置当更美妙。此处只聊“50摆设毛爷爷内足以打至哪边的微单”。

  (5)可以由此反射机制变动态代理。

❶ “鱼与熊掌兼得”:Sony A6000

先是介绍Sony是盖它时尚时尚最时尚:不仅是说外形,而是说以总体微单界索尼是引领潮流的大咖。

孟子老人家都操:鱼和熊掌不可兼得,大概可以据此来描述相机这点从:如果想如果画质好,性能大,通常状态下便见面促成相机体量较生是携带;而而惦记达到轻便就要放弃一些特性。Sony却浓地反映出自己技术控的原形,就是若于当下两者之间达到极端要命平衡,呢不断一个人数说,“微单拯救了索尼的照相机。”索尼的微单分为全幅和APS-C画幅,全幅相机包括刚提到的A7R2暨A7普系列,无论是画质还是外形都可圈可点,在无输给单反全画幅机的还要,还能保持小巧的机身。

于刚刚沾摄影之总人口而言,从价格、配置以及需要达到看,可少未欲入手全画幅相机。因此推荐索尼的APS-C画幅微单:Sony
A6000。

除却有的科普功能布局外,一反对于微单相机对焦慢的熊,A6000在对焦技术上闹美的升迁,采用4d对焦,融入时间维度概念,实现了过四个维度追踪被摄物。

  3、Talk is cheap,show me the code. 来平等组反射机制小示例

❷ 复古是千篇一律种致病:Fujifilm X-M1/X-T10

缘何原始之物往往很有魅力?大概是盖于世界更复杂的时候,纯粹而简约的事物更加发得人心。所以我认的绝大多数文学青年都有复古病,包括自己要好在内。

多人心里中之相机便是这种极端古老的旗帜,无奈之凡,除了发生特有爱好,大多数人口曾习以为常用“Byte”而非是胶片储存图像,数码成像的好处虽在非一次性,你可来来去去地游玩转直到打到祥和看中了。也恰好为当时特色,摄影才叫越来越多的人口所迷。想只要以得到数码相机和复古外形,那么您的抉择虽是这家以复古风闻名的厂家的微单,Fujifilm富士。

Fujifilm
X-M1凡是平等慢性高性价比的APS-C画幅微单,外形复古,体量轻盈。难得之是,这样的有点机型上布置了高端的性,采用自Trans-CMOS传感器,高感与画质更好,还有wifi、翻转屏等人性化安排。遗憾之是,X-M1推脱掉了电子取景器,只能通过显示屏来取景,这一点或许未切合众多口之气味,因为无法做出这文学之相了:

如若预算充足,可以设想富士新推出的X-T10。

她叫许多总人口写呢当时富士旗舰机X-T1之低端版。虽然一贯并无是不行分明,但是及时不伤它当APS-C画幅微单领域的优越性。综合性能与富士先前之X-E2不相上下,但也具有更小之定价。不仅要复古的外形,还要复古之操纵。三单可调动参数的转盘可供应玩家自行定义自己的拍摄模式,但也设想到了有些一味想拍的用户:

“一键到位的AUTO档,这个高速设置档迅速解决了符门级用户的要求,在发布会及富士的工作人员说的一些充分好,他添加了用户的界定,因为这规划元素的融入,家庭用户拍照的或许不单独是爱好摆弄机械的父,还有仅仅想按部就班快门的慈母。”——网络同样篇测评中的相同截话。

除开增添全自动模式之外,X-T10底对焦速度吗取得了提升。

三款机型的价钱由没有到高:X-M1<X-T10<X-E2。根据自己之预算和急需,对比得出购买决策吧。

  首先创建一个类供反射调用测试用,暂且将类名
BeReflected,并在近似吃补充加点儿只分子变量、三独平常方法、一个静态变量,一个静态方法,具体代码如下:

❸ 其它推荐

微单还可考虑的品牌包括Olympus/奥林巴斯、Panasonic/松下等。例如让称作
“自拍小七”的Olympus Pen e-pl7,想必会为众多女生青睐。

 1 /**
 2  * 被反射测试的类
 3  * Created by liuwei on 17/4/2.
 4  */
 5 public class BeReflected {
 6     private String field1 = "I am field1";
 7     private String field2 = "I am field2";
 8     private static String staticField = "I am staticField";
 9     private void method1(){
10         Logger.i(BeReflected.class, "I am method1");
11     }
12     private void method1(String param) {
13         Logger.i(BeReflected.class, "I am method1--param = " + param);
14     }
15     private void method2(){
16         Logger.i(BeReflected.class, "I am method2");
17     }
18     public static void staticMethod(){
19         Logger.i(BeReflected.class, "I am staticMethod");
20     }
21 }

老三类镜头

常听到玩摄影的意中人口中出现同等众动物与其的峰:小白及小白兔,狗头,牛头,驴头等等ORZ。稍作了解才知这实际是……镜头啦!一般而言,成像质量和价格还是:牛头>驴头>狗头。

选购相机时可择打裸机即只有机身,或者诸如大多数人口一如既往打套机即机身加套头,但如想要于照相(shāo)影(qián)这漫长路上越走越远,就要及时地选择符合自己需求的画面,用作进阶使用。除了腾龙、适马等特别产镜头的厂商,通常镜头和相机的品牌要彼此对应。

针对入门发烧友,最好打1就生转移焦镜头入手,逐渐领悟不同焦距和拍照视角、构图之关系,再冲实际情况与特定需求购入定焦镜头

针对单反而言,如果您时常于某些场景下拍某些事物,可能来以下这些:

  (1)通过反射获取 BeReflected 的Class类型,并拿那初始化。(其中
Logger 是楼主封装的一个日记打印类,无需在一点一滴这些细节)

❶ 拍人像:SIGMA/适马 50mm f/1.4 镜头

乃早晚见了无数接近这样的相片:

“主体突出,背景虚化”是碰撞人像时常因此之留影技巧。设若达成这种功能待镜头的大光圈,营造起极其之浅景深虚化效果,柔和的焦外成像可比较好地将给摄主体由背景中分离开。还需要配合适当的焦距,通常也50mm/85mm。

85mm’是常用之人像焦段,佳能的“大眼”EF 85mm f/1.2L II USM和尼康底 AF-S
85mm
f/1.4G还是优之人如镜头,适合有全画幅相机的发烧友使用。对于有所APS-C画幅相机的入门爱好者来说,可以选择50mm
f/1.4之画面来拍摄人像,因为画幅不同相当给80mm的效能。同时,50mm焦段作为正式镜头,也适合入门爱好者学习使用。

1 // 1、通过反射获取BeReflected所属的类
2 Class<?> beReflectedClass = Class.forName("com.liuwei.proxy_hook.reflect.BeReflected");
3 Logger.i(ReflectTest.class, beReflectedClass);
4 
5 // 2、通过反射创建实例化一个类
6 Object beReflected = beReflectedClass.newInstance();
7 Logger.i(ReflectTest.class, beReflected);

❷ 爱扫街:SIGMA/适马 35mm F1.4 DG HSM 镜头

本着喜欢人文的发烧友等的话,“见闻”就变成相机取景的问题。许多文青常常坐及照相机来门扫街,用之几近是35mm焦段,鉴于视角不是生非常,因而边缘变形也针锋相对还有些。f1.4的大光圈又满足背景虚化的用。这款镜头是适马(SIGMA)全球视野新画面的首款产品,也是ART系列的首款产品,除拍人文外,在景观、人像、静物、
特写等多只领域还生是的显现。

Adrian Petrisor的人文摄影作品

而相对来说更推荐尼康用户着想这款镜头,佳能用户可同时考虑 EF 35mm F2 IS
USM。

  输出如下:

❸ 去探险:Tamron/腾龙 AF18-200mm F/3.5-6.3 镜头

对于广大喜爱户外旅行和探险的驴友来说,行走着之随时记录必要。大多数照相机还发生不错的防范水防摔性能,除机身的份量需考虑他,探险时捕捉眼前之景点,焦距的有益调整成为任何一个第一元素。18-200变焦镜头既可是用作入门爱好者学习照之挑,也只是作为户外摄像之“驴头”一镜子走世界采取。除相机品牌自己的镜头外,这同样款款镜头是是的选择。

  [ReflectTest] : class
com.liuwei.proxy_hook.reflect.BeReflected
  [ReflectTest] :
com.liuwei.proxy_hook.reflect.BeReflected@7d4991ad

❹至于微单

除去与自家品牌互动呼应的不等条件镜头外,前文与单反对比时涉嫌,微单因为法兰距相对单反较短,因此好转账更多种类型的画面。

对镜头而言,法兰焦距是恃镜头太远对焦时,镜头卡口平面及镜头可以像面(即透镜焦点)之间的距离。对机身而言,法兰焦距是赖卡口到焦平面(即CCD或CMOS所于的面)之间的偏离。当然同一卡口的话,机身法兰焦距和画面法兰焦距是当的,即一律种植卡口只发一个法兰焦距。(摘自百度百科)

生图是几单品牌常见卡口的法兰距数值比:

不过看,微单的法兰距要少许多。这意味着一旦添加尺寸合适的转接环将相面距加长到同单反一致就会下只反镜头。给镜头加距离是相对轻松能兑现之工作,但让长距离缩短则不然。所以来诸多总人口表示,一些被年代尘封的尽镜头为为微单的产出更焕发生命力。

完整来说,单反相机适配的镜头系统性、专业性更胜,更合乎进阶、钻研;微单相机适配镜头则备双重老的八面玲珑,更符合玩转、尝鲜。

照相这档子小事,并不一定需要多耸动的问题,也非欲极高端的配备。安德烈柯特兹就是同员将在小型相机走会串巷的摄影师,从来还只有对凡的路口人生情有独钟。他就说:“相机是自的工具,经由它,我与自己周遭的有所东西一个说辞。”不了及时理由,需要你自己去与。

附带给你们推荐这部影片吧:

她躲在三年未发底房间里,每天的娱乐活动就是叫月亮拍照。每年鲜糟糕的防空演习,大街上空无一致人口常常,是它们会客打开窗子用相机肆意眺望世界之随时。直到她当相机里发现了相同栋岛屿,岛及起一个疑似外星来的女婿…

录像《金氏漂流记》

而今,你出记录世界之冲动了么

  (2)通过反射访问私有方法及民用成员变量,并更改私有变量的价值。我们还了解,对于一个私房类型的变量,在无供公开之
set 之类方法的状下,想改它的价值是免容许的,但是利用反射就得成功。

 1 // 3、通过反射调用一个私有方法和成员变量
 2 Method method = beReflectedClass.getDeclaredMethod("method1");
 3 method.setAccessible(true);// 将此值设为true即可访问私有的方法和成员变量
 4 method.invoke(beReflected);// 访问普通成员变量和方法是需要在调用invoke方法是传入该类的对象
 5 
 6 Field field1 = beReflectedClass.getDeclaredField("field1");
 7 field1.setAccessible(true);
 8 Logger.i(ReflectTest.class, "field 改变前的值:" + field1.get(beReflected));
 9 field1.set(beReflected, "我是 field1 被改变后的值");
10 Logger.i(ReflectTest.class, "field 改变后的值:" + field1.get(beReflected));

  输出如下:  

  [BeReflected] : I am
method1
  [ReflectTest] : field
改变前之值:I am field1
  [ReflectTest] : field
改变后底价:我是 field1 让转移后底价值

   (3)通过反射访问静态方法和静态变量。访问静态方法和变量时莫需要传入所属类的对象,传入
null 即可访问。代码如下:

1 // 4、通过反射调用一个静态的方法和变量
2 Method staticMethod = beReflectedClass.getDeclaredMethod("staticMethod");
3 staticMethod.invoke(null);
4 
5 Field staticField = beReflectedClass.getDeclaredField("staticField");
6 staticField.setAccessible(true);
7 Logger.i(ReflectTest.class, staticField.get(null));

  输出如下:

  [BeReflected] : I am
staticMethod
  [ReflectTest] : I am
staticField

  (4)通过反射访问一个带动参数的法门。访问带参数的方是,需要在
getDeclareMethod 后面传来一组参数的品类。

1 // 5、通过反射访问一个带参数的方法
2 Method method1 = beReflectedClass.getDeclaredMethod("method1", String.class);
3 method1.setAccessible(true);
4 method1.invoke(beReflected, "我是被传入的参数");

  输出如下:

  [BeReflected] : I am
method1–param = 我是为传出的参数

   (5)通过反射获取类吃有的成员变量和艺术。

1 // 6、遍历类中所有的方法和成员变量
2 for (Method tempMethod : beReflectedClass.getDeclaredMethods()) {
3     Logger.i(ReflectTest.class, tempMethod.getName());
4 }
5 for (Field tempField : beReflectedClass.getDeclaredFields()) {
6     Logger.i(ReflectTest.class, tempField.getName());
7 }

  输出如下:

  [ReflectTest] :
method2
  [ReflectTest] :
method1
  [ReflectTest] :
method1
  [ReflectTest] :
staticMethod
  [ReflectTest] :
field1
  [ReflectTest] :
field2
  [ReflectTest] :
staticField

  看罢上面几乎独例子之后,你是无是看反射还真是神奇,可以好多为此健康办法做不交之操作。当然者只是示例了映机制中极基本的局部调用而已,感兴趣之意中人可以活动查阅官方文档。废话不多说了,我们抢上马介绍
Hook 技术。

二、Hook入门

  Hook 中文释意是“钩子”,这片天楼主为直接以镂,Hook
到底指的凡呀?如何才会为此相同种植简单好掌握,生动形象的讲来提现 Hook
技术?以楼主目前对 Hook
的明白,通俗来将就是通过某种手段对同样码东西进行偷梁换柱,从而劫持目标来坐高达控制目标的所作所为的目的。从技术角度来说,就是替换原有的目标,拦截目标函数/方法,从而改变其原本的行。

  在3月份初刚起读 Hook
技术时写了一个关于替换汽车发动机的小例子,今天便把此事例贴出吧。先说一下横流程,首先我们会起一个简单易行的汽车类,汽车类里面有个引擎的目标,当然,汽车发动机都是来正式的(这里就为接口),为简便起见,我们这里的汽车发动机标准且只来一个极度酷快的指标,后续我们会由此反射机制来替换掉汽车引擎以达到提高极端可怜快之目的。例子非常简单,通过此事例我们很轻就可知起的喻
Hook 技术。

  汽车类代码如下:

 1 /**
 2  * Created by liuwei on 17/3/1.
 3  */
 4 public class Car {
 5     private CarEngineInterface carEngine;
 6     public Car() {
 7         this.carEngine = new CarEngine();
 8     }
 9     public void showMaxSpeed(){
10         Logger.i(Car.class, "我卯足劲,玩命跑的最大速度可以达到:" + carEngine.maxSpeed());
11     }
12 }

  可以见见,汽车类里面有一个 carEngine
(汽车引擎)的属性,汽车发动机接口代码如下:

1 /**
2  * 车引擎接口
3  * Created by liuwei on 17/3/1.
4  */
5 public interface CarEngineInterface {
6     int maxSpeed();
7 }

  汽车引擎类代码如下:

/**
 * 车引擎
 * Created by liuwei on 17/3/1.
 */
public class CarEngine implements CarEngineInterface {
    @Override
    public int maxSpeed() {
        return 60;
    }
}

  一个简约的小车搞定了,试跑一下:

1 public class Test {
2     public static void main(String[] args) {
3         Car car = new Car();
4         car.showMaxSpeed();
5     }
6 }

  输出结果:[Car] :
我卯足劲,玩命跑的极其特别快可以达成:60

  额…好吧,卯足劲才能够跑至60,这发动机速度发出点….,作为一个飙车党,肯定不克忍心,必须改装!

  以改装之前,我们要事先考察从何下手合适,可以看来,在 Car
类里面来只 CarEngine 的对象,我们要开的虽是拿此 CarEngine
的靶子替换成我们好创立的引擎类,这个引擎类需要出就同 CarEngine
一样的特色,也就是说要贯彻 CarEngineInterface 接口或者直接接轨
CarEngine ,然后拦截到 maxSpeed
方法并修改返回值。那么这里我们实际有点儿栽方案,一种植方案,可以又创设一个引擎类,让其继承
CarEngine 或者实现 CarEngineInterface 都实施,然后经过反射来替换 Car
对象中之 carEngine 属性;另一样种植方案,写一个动态代理,让该对 CarEngine
进行代理,然后据此反射替换。

  第一种方案:

  首先创建一个 EvilCarEngine 类, 详细代码如下:

 1 /**
 2  * Created by liuwei on 17/3/1.
 3  */
 4 public class EvilCarEngine extends CarEngine {
 5     private CarEngineInterface base;
 6     public EvilCarEngine(CarEngineInterface base) {
 7         this.base = base;
 8     }
 9     public int maxSpeed() {
10         return 3 * base.maxSpeed();
11     }
12 }

  然后因故反射机制替换掉原来的汽车引擎。

 1 public class Test {
 2     public static void main(String[] args) {
 3         Car car = new Car();
 4         Logger.i(Test.class, "------------------替换前----------------");
 5         car.showMaxSpeed();
 6         // 怎样在不手动修改CarEngine类和Car类的情况下将大速度提高?
 7         try {
 8             Field carEngineField = Car.class.getDeclaredField("carEngine");
 9             carEngineField.setAccessible(true);
10             CarEngine carEngine = (CarEngine)carEngineField.get(car);
11             // 方法1
12             carEngineField.set(car, new EvilCarEngine(carEngine));
13         } catch (Exception e) {
14             e.printStackTrace();
15         }
16         Logger.i(Test.class, "------------------替换后----------------");
17         car.showMaxSpeed();
18     }
19 }

   输出结果:

  [Test] :
——————替换前—————-
  [Car] :
我卯足劲,玩命跑的极端特别快好达成:60
  [Test] :
——————替换后—————-
  [Car] :
我卯足劲,玩命跑的不过可怜快可达标:180

  第二种植方案:

  首先创建一个动态代理类,并阻挠 maxSpeed 方法,修改返回值。

 1 /**
 2  * Created by liuwei on 17/3/1.
 3  */
 4 public class CarEngineProxyHandler implements InvocationHandler {
 5     private Object object;
 6     public CarEngineProxyHandler(Object object) {
 7         this.object = object;
 8     }
 9     @Override
10     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
11         if ("maxSpeed".equals(method.getName())) {
12             Logger.i(CarEngineProxyHandler.class, "我是动态代理,我已拦截到 maxSpeed 方法,并偷偷返回了另一个值!");
13             return 180;
14         }
15         return method.invoke(object, args);
16     }
17 }

   同理,利用反射替换掉原来的汽车发动机

 1 public class Test {
 2     public static void main(String[] args) {
 3         Car car = new Car();
 4         Logger.i(Test.class, "------------------替换前----------------");
 5         car.showMaxSpeed();
 6         // 怎样在不手动修改CarEngine类和Car类的情况下将大速度提高?
 7         try {
 8             Field carEngineField = Car.class.getDeclaredField("carEngine");
 9             carEngineField.setAccessible(true);
10             CarEngine carEngine = (CarEngine)carEngineField.get(car);
11             // 方法2
12             CarEngineInterface carEngineProxy = (CarEngineInterface) Proxy.newProxyInstance(
13                     CarEngine.class.getClassLoader(), 
14                     new Class[]{CarEngineInterface.class}, 
15                     new CarEngineProxyHandler(carEngine));
16             carEngineField.set(car, carEngineProxy);
17 
18         } catch (Exception e) {
19             e.printStackTrace();
20         }
21 
22         Logger.i(Test.class, "------------------替换后----------------");
23         car.showMaxSpeed();
24     }
25 }

  输出结果与方案一一致。

  写及这边,Hook 的骨干用法吧就勾勒了了,看罢例子之后,或许你已经对
Hook 有了一个主导的认,但值得一提的凡,在 Test
类中的第10行代码中我们率先取出了 Car 中的 carEngine
对象,然后将是目标传入了它的替罪羊中,为什么要这样做的,在替身中莫传播
carEngine 或者更 new 一个初的 CarEngine
不行吧?这是一个至关重要点,我们得掌握的凡,这里我们只是怀念改一下发动机的极充分快,而并无期待引擎的别样属性被震慑,我们将自
Car 中取出原有的 carEngine
对象传入替身中,这样替身就好就选取我们关注的计进行修改,对于咱们无思改的艺术直接调用传经来之
carEngine
对法即可。因为此的例证为了简单打表现没长其它的法子与总体性,所以这一点内需重点说明一下。

三、小结

  其实 Hook 技术简单来说可以为此替换、拦截来描写,并无以新技巧。Hook
本身并无碍事,它的难题在于你以对同段子代码 Hook 之前用找来一个恰如其分的 Hook
点,也就是说分析有从哪下手很要紧,这就算要求您对将 Hook
的靶子代码的尽流程很熟悉。本篇博文只是开端认识一下 Hook
技术,下一致首博文将会介绍如何通过 Hook 技术阻碍 Android 中 startActivity
方法,并于分析的进程中介绍如何才是适用的 Hook
点。感兴趣的恋人可关注一下,敬请期待!

本文地址:http://www.cnblogs.com/codingblock/p/6642476.html