Java: Hook技术[通俗易懂]

Java: Hook技术[通俗易懂]一、什么是Hook  Hook翻译成中文就是勾子的意思,在java中它表示在事件到达终点前进行拦截或监控的一种行为。 二、Hook的实现实现hook我们必须要知道java的反射和动态代理。 1、反射  反射是java的查看、检测、修改自身的一种行为。  在编译阶段,编译器将我们编写的java文件编译成.class文件。而在运行期,jvm又将.class文件通过…

大家好,又见面了,我是你们的朋友全栈君。

一、什么是Hook

   Hook翻译成中文就是勾子的意思,在java中它表示在事件到达终点前进行拦截或监控的一种行为。

 

二、Hook的实现

实现hook我们必须要知道java的反射和动态代理。

 

1、反射

   反射是java的查看、检测、修改自身的一种行为。

   在编译阶段,编译器将我们编写的java文件编译成.class文件。而在运行期,jvm又将.class文件通过类加载器ClassLoader加载一个类对应的Class对象到内存当中。通过修改Class对象,达到我们查看、检测、修改自身的行为。

   Class clazz = Class.forName(“android.com.test.TestClass”),方式加载类的class文件。

   生成实例的方法不一定通过new ,可通过下面的方法获取Class对象对应的实例

Constructor constructor = clazz.getConstructor();
TestClass o =  (TestClass)constructor.newInstance();

当然,构造函数可能有多个,你应该通过获取他的所有构造函数。了解到他的构造函数之后再使用上面的方法,不然会报错

Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors){
    constructor.setAccessible(true); //可能有些构造函数你的权限不够,让其可能反射
    Class[] params = constructor.getParameterTypes(); //某个构造函数的参
    Log.i("tag",String.valueOf(params.length)); //看看构造函数参数的长度
    for (Class p : params) {
        Log.i("tag","参数类型的名字"+p.getName()); //看看这个构造函数是什么类型
    }
    }
}

同理,通过class类对象,可以获取对象的方法。动态代理中需要在方法拦截。

Methods  method[] = clazz.getDeclaredMethods();

获取对象的域,

Field[] fields = clazz.getDeclaredFields()

获取对象的注解,我们ButterKnife就是运用到了这个。

Annotation[] annotations = hookUserClass.getDeclaredAnnotations();
for (Annotation annotation : annotations){
    Log.i("tag","注解类型class文件的名字"+annotation.annotationType().getName());
}

 

 

  

2、动态代理

    动态代理相对静态代理而言,动态代理是动态的,通过反射对被代理对象的方法,代理成代理对象对应的方法。动态代理也运用到了反射的知识。

final Leader leader = new Leader(new Worker());
IPerson IpensonImp = (IPerson) Proxy.newProxyInstance(Leader.class.getClassLoader(),new Class[]{IPerson.class}, new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        method.invoke(leader,args); 
        return proxy;
    }
});
Field[] fields = clazz.getClass().getDeclaredFields();
for (Field field : fields){
    field.setAccessible(true);
    if (field.getName().equals("iPerson")){
        try {
            field.set(clazz,IpensonImp);  
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        break;
    }
}
hookUser.doWhat();
 class TestClass{
    IPerson iPerson ;
    public HookUser(){
        iPerson = new Worker();
    }
    public void doWhat(){
        iPerson.say("我是工人");
    }
}
public class Leader implements IPerson{
    IPerson iPerson;

    public Leader(IPerson iPerson) {
        this.iPerson = iPerson;
    }

    @Override
    public void say(String what) {
        PrintUtils.print("我领导,我叫我去说");
        iPerson.say(what);
        PrintUtils.print("事情干完了");
    }

    @Override
    public void walk(String where) {
        PrintUtils.print("我领导,我叫我手走过去");
        iPerson.walk(where);
        PrintUtils.print("事情干完了");
    }
}

 

public class Worker implements IPerson {
    @Override
    public void say(String what) {
        PrintUtils.print(what);
    }

    @Override
    public void walk(String where) {
        PrintUtils.print(where);
    }
}

三、Hook的条件

   如上面代码,运用反射和动态代理,可实现将TestClass中 IPerson iPerson 指向的Worker对象,动态修改为Leader对象,实现了hook的过程。那么实现hook需要什么条件呢?

    1、代理对象和被代理对象需要实现同样的接口,Leader和Worker都是iPerson的实现类。

    2、被代理对象必须在使用的时候,使用接口作为类型。否则不能被动态代理。  field.set(clazz,IpensonImp)会报错,类似设置错误。

    3、此案例中hook的对象是TestClass。一次修改后被系统回收后,hook就失效了。如果要长期生效,那么hook的生命周期应该是对应响应的生命周期,如应用全局的生命周期,如单例等。

 

     

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141464.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • graduation和completion_guides和maven区别

    graduation和completion_guides和maven区别参考:androidgradle依赖:implementation和compile的区别2017年google后,Androidstudio版本更新至3.0,更新中,连带着com.android.tools.build:gradle工具也升级到了3.0.0,在3.0.0中使用了最新的Gralde4.0里程碑版本作为gradle的编译版本,该版本gradle编译速度有所加速,更加……

    2022年10月26日
    0
  • HttpSession的正确理解

    HttpSession的正确理解一个session就是一系列某用户和服务器间的通讯。服务器有能力分辨出不同的用户。一个session的建立是从一个用户向服务器发第一个请求开始,而以用户显式结束或session超时为结束。其工作原理是这样的:当一个用户向服务器发送第一个请求时,服务器为其建立一个session,并为此session创建一个标识号;这个用户随后的所有请求都应包括这个标识号。服务器会校对这个标识号以判断请求属于…

    2022年7月13日
    15
  • 二进制与十进制的讲解与转换「建议收藏」

    二进制与十进制的讲解与转换「建议收藏」文章目录?什么是十进制呢??什么是二进制??十进制和二进制之间可以转换吗??十进制与二进制之间的转换?二进制转十进制?十进制转二进制?写在最后哈喽,大家好!这是我的第一篇博客,就先来介绍一下自己吧,我是Why,一名在读学生,目前刚刚开始进入自己的编程学习生涯。虽然学习起步较晚,但我坚信做了才有0或1的可能。学了一段时间以后也是选择在CSDN上分享自己的日常笔记,也希望能够在众多道友的大家庭中打成一片。本文主要讲解二进制以及进制之间的转换,如果大家读后觉得有用的话,还请大家多多支持博主:欢迎❤️点赞

    2022年10月18日
    0
  • Android N特性解析

    Android N特性解析作者:Redyan,腾讯移动客户端开发工程师商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处。原文链接:http://wetest.qq.com/lab/view/288.html

    2022年7月3日
    19
  • idea添加tomcat插件_tomcat配置idea

    idea添加tomcat插件_tomcat配置idea配置tomcat插件,一直报错,自己一点儿一点儿排错,一点儿一点儿,心态都要奔溃了,搜索了很多的教程都不行,花了34个小时,终于可以了,下面是错误信息,还有另一个但是我没来的及复制另一个错误信息,抱歉。错误信息:严重:Errorconfiguringapplicationlistenerofclassorg.springframework.web.context.ContextLoaderListenerjava.lang.ClassNotFoundException:org.sp

    2022年10月10日
    0
  • 四级英语词汇大全(英语四级词汇表完整版)

    aart.一(个);每一(个)a.m(缩)上午,午前abandonvt.丢弃;放弃,抛弃abbreviationn.节略,缩写,缩短abilityn.能力;能耐,本领ablea.有能力的;出色的abnormala.不正常的;变态的aboardad.在船(车)上;上船abolishvt.废除,取消aboutprep.关于;在…周围aboveprep.在…上面;高于abroadad.(在)国外;到处absencen.缺席,不在场;缺乏absenta.不在场的

    2022年4月11日
    149

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号