文章目录
-
- 静态代理
- 动态代理
- 原理
- hook动态代理getHardwareAddress
-
- @UnsupportedAppUsage
- 代理对象在动态代理中的生成过程
- getHardwareAddress怎么获取Mac地址
- InetAddress类和NetworkInterface类
- android获取有线网Mac地址
- 动态代理的核心原理
- JAVA基础-反射、反射详细介绍、类加载、反射获取参与结构、获取方法、获取属性、跨泛检查、动态代理
- libcore.io.Libcore动态代理
- MzPush SDK魅族推送导致隐私不合格
代理可以增强或拦截方法,修改原方法的参数和返回值
静态代理
定制一个类implements在接口中实现方法 这种方法需要为每个代理人写一个自定义类,不能拦截
动态代理
JVM在运行过程中动态生成一系列代理 就是hook方法 先找点需要hook静态变量或单例对象
注意jdk动态代理只能代理接口,所以如果你想代理,你需要手写静态代理覆盖原始方法
使用Class.forName(“模块名.包名.类名.可获得某一参数类型的类型名称 比如Class.forName(“android.net.wifi.IWifiManager”); 类名.class.getDeclaredField(变量名);可以获得某一类的变量 比如 serviceField = WifiManager.class.getDeclaredField(“mService”); 这个mService变量的类型是IWifiManager 该变量的可控性可以设置为 serviceField.setAccessible(true);
这个IManager类型的service获取了 但是实际的WiFi使用管理器app从系统服务中获得的上下文 然后使用这个IWifiManager获取服务变量app的原生wifiobj,把这个wifiobj引入自定义操作触发器获取自定义触发器的代理实例 之后使用Imanager服务变量类型set方法,传入现有获得的方法WiFi管理和使用这个WiFi管理器的WiFiobj重构的WiFi管理器 新的WiFi管理器需要通过反射中的代理方法进行重构和处理,需要引入WiFi服务变量缓存,这个WiFi新的服务类实例和自定义重构WiFi只有当服务被触发时,才能得到真正的方法WiFi控制器类
现在需要动态代理的是getHardwareAddress该方法的控制方法是什么? 这个方法在NetworkInterface。java里 因此,我们需要取代这一类,然后重新获取硬件信息
原理
Subject subject = new RealSubject(); ProxySubject proxy = new ProxySubject(subject); Subject sub = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), proxy); sub.operation();
public class ProxySubject implements InvocationHandler{
protected Subject subject; public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//do something before
return method.invoke(subject, args);
}
}
public class RealSubject implements Subject{
@Override
public String operation() {
return "operation by subject";
}
}
public interface Subject {
String operation();
}
其优点是扩展和隐私,对外只提供一个代理访问,只有我自己可以用真正的类做操作。安卓系统中大量用到代理模式,比如获取系统的服务,App进程只能拿到服务的代理对象。 https://blog.csdn.net/nannan1989yue/article/details/118297436
代理两个方式 静态代理在编译的时候已经确认自己的任务 比如一个接口,然后一个实现这个接口的实现类
写一个代理类是把原先的实现类定义为变量在重新的方法里做一些拦截处理后重新调用实例方法 然后使用:接口名表示是哪个接口的实现类
这样要写很多代理类
所以动态代理,运行的时候才开始代理 动态代理要配合proxy类和InvocationHanlder接口重写invoke方法来实现
先获取类,之后获取某个参数 之前实现的动态代理WifiManager类的时候是先获取WifiManager对应的接口IWiFiManager的,分享WiFimanager里面的getConnectionInfo方法的时候,可以看懂返回的实际是是MService.getConnectionInfo方法 先使用app上下文获取系统WiFi服务也就是一个,之后使用servicefield获取到WiFimanager
hook动态代理getHardwareAddress
https://bbs.pediy.com/thread-215039.htm https://www.open-open.com/lib/view/open1494401599694.html InvocationHandler 接口和 Proxy 类 Java 编译器编译好 Java 文件之后会在磁盘中产生 .class 文件 .class 文件是二进制文件,内容是只有 JVM 虚拟机才能识别的机器码,JVM 虚拟机读取字节码文件,取出二进制数据,加载到内存中,解析 .class 文件内的信息,使用相对应的 ClassLoader 类加载器生成对应的 Class 对象
class 字节码文件是根据 JVM 虚拟机规范中规定的字节码组织规则生成的,具体的 .class 文件格式介绍可以查看博客 深入理解Java Class文件格式 和 Java 虚拟机规范
JVM 是通过字节码的二进制信息加载类的,那么我们如果在运行期系统中,遵循 Java 编译系统组织 .class 文件的格式和结构,生成相应的二进制数据,然后再把这个二进制数据转换成对应的类,这样就可以在运行中动态生成一个我们想要的类
Java 中有很多的框架可以在运行时根据 JVM 规范动态的生成对应的 .class 二进制字节码,比如 ASM 和 Javassist 等
这样先获取要替代的类的一个实例 分析一下要取代的方法 里面先是定义了一个networkInterface变量,这个变量是使用getByName(name)方法获取的,这个方法是静态方法,需要往里面传入一个string类型的name变量,这个方法里先使用getAll获取所有的NetworkInterface[]变量,之后遍历这个变量里的所有元素,然后看看所有的NetworkInterface列表里哪个是要找的哪个name的networkInterface实例 getHardwareAddress获取的是某个name的networkInterface实例里的Mac地址,没有这个实例会报错,实际上这个类的构造方法 想要取得NetworkInterface对象,就必须要通过NetworkInterface类的public staticEnumeration getNetworkInterfaces()方法,该方法的返回值是泛型Enumeration,作用是返回此机器上的所有接口 https://blog.csdn.net/cold___play/article/details/106600394
NetworkInterface同样没有提供公开的构造函数,而是提供一些静态方法来获取实例 static NetworkInterface getByInetAddress(InetAddress addr)搜索绑定了制定IP地址的网络接口 static NetworkInterface getByName(String name)搜索具有指定名称的网络接口 static Enumeration getNetworkInterfaces()返回本机所有网络接口的一个枚举实例
{
'methodName':'getData','lineNumber':488,'className':'libcore.util.Janus','fileName':'Janus.java','level':0},{'methodName':'getHardwareAddress','lineNumber':565,'className':'java.net.NetworkInterface','fileName':'NetworkInterface.java','level':0}
getHardwareAddress()里使用了getByName(name),这个方法又使用了getAll(),里面定义了StructIfaddrs[] ifaddrs; 实际上应该代理这个方法 getHardwareAdress里返回使用getByName获取到的NetworkInterface变量的hardwareAddr 所以这个方法最终调用的是getAll方法获取所有的Networkinterface变量,这个是一个private方法 NetworkInterface ni = new NetworkInterface(name, index, null);
private static NetworkInterface[] getAll() StructIfaddrs StructIfaddrs[] ifaddrs; ifaddrs = Libcore.os.getifaddrs() https://www.thinbug.com/q/35193646 getAll方法必须调用的变量是StructIfaddrs[] ifaddrs,这是一个field变量 libcore.io.Libcore
@UnsupportedAppUsage
https://blog.csdn.net/Mr_theSun/article/details/89607608
动态代理里代理对象的生成过程
https://www.open-open.com/lib/view/open1494401599694.html 先获取原型对象的所有的接口列表 确定一下要生成的代理类的类名 根据要实现的接口信息在代码里动态创建代理对象类的字节码 把对应的字节码转换成对应的class对象 创建一个invokecat戳你Handler的实例对象用于处理代理角色的所有方法调用,用创建的实例对象实例化一个代理角色
真的类实现对应的接口,代理类实现的是InvocationHandler接口,里面重新一个invoke方法,这个方法里
新建一个原型对象实例,然后新建一个代理对象实例(实例化的时候传入原型类实例),然后使用代理类
这个代理的对象需要新建一个代理实例,往代理实例里传入要替代的类的缓存,类的实例和替代料,然后执行代理类的opration方法就开始在运行过程替代所有方法了 当然也可以使用一些set方法
getHardwareAddress怎么获取Mac地址
https://blog.csdn.net/qq_43080741/article/details/124237926 产品地址和Mac地址都是在计算机里用二进制表示的,ip地址是32位。mac是48位
InetAddress类和NetworkInterface类
https://blog.csdn.net/lizefeng1998/article/details/121088480 java.net.InetAddress类是Java对IP地址的高层表示。一般来说,它包括一个主机名和一个IP地址
NetworkInterface类表示一个本地的IP地址,这可以是一个物理接口,如额外的以太网卡(常见于防火墙和路由器),也可以是一个虚拟接口,与机器的其他IP地址绑定到用一个物理硬件
NetworkInterface有两个构造自身实例的静态工厂方法
public static NetworkInterface getByName(String name) 表示有指定名字的网络接口
public static NetworkInterface getByInetAddress(InetAddress address) 表示与指定IP地址绑定的网络接口。
NetworkInterface还提供了一个getNetworkInterfaces()函数,该方法会返回一个java.util.Enumeration,他会列出本地主机上所有的网络接口
,NetworkInterface.getHardwareAddress()但这是针对API级别9和更高版本的 该API的level为9,只有android 2.3以上才有该接口
https://blog.chinaoc.com.cn/p/1236387.html
android获取有线网的Mac地址
https://blog.csdn.net/nihenbuhao/article/details/53150027
InetAddress ip = getLocalInetAddress();
byte[] b = NetworkInterface.getByInetAddress(ip)
.getHardwareAddress();
https://blog.csdn.net/nihenbuhao/article/details/53150027
动态代理核心原理
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
....}
————————————————
版权声明:本文为CSDN博主「Android_HQK」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_30382601/article/details/118450742
loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载 interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。
JAVA基础——反射,反射详细内容介绍,类加载,反射获得有参无参构造,获取方法,获取属性,越过泛型检查,动态代理
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化
jdk只能代理接口 https://wenku.baidu.com/view/5d56068b2b4ac850ad02de80d4d8d15abe2300ea.html
libcore.io.Libcore动态代理
https://blog.csdn.net/lzz137/article/details/116095873 android OS是一个io回调,是想动态代理 android.system.StructIfaddrs Libcore.os.getifaddrs()
通过动态代理AndroidOs,调用Os.compareAndSetDefault进行替换 看看里面的os赋值 class静态初始化的时候赋值一次,compareAndSetOs函数调用的时候赋值一次
安卓系统调用的是compareAndSetOs函数,设置了os回调,这个是调用了compareAndSetOs函数 ActivityThread.java调用compareAndSetOs函数
MzPush SDK魅族推送导致隐私不合格
http://open.res.flyme.cn/fileserver/upload/file/202109/7bf101e2843642709c7a11f4b57861cd.pdf
删除无关权限–图片,媒体内容和文件