classLoader动态加载技术
阅读原文时间:2023年07月09日阅读:1

//加载器,apkPath为包含dex文件的.apk或jar路径,dexPath是优化后的dex文件路径,第三个表示libraryPath表示Native库的路径,最后是父类加载器

DexClassLoader classLoader= new DexClassLoader(apkPath, dexPath,null,getClassLoader());

try{

     //类,在加载类时,先检查父类是否已经加载过这个类?

     Class mLoadClass=classLoader.loadClass("com.example.dexClassloaderslave.DexSlave");

     //构造器

     Constractor constructor=mLoadClass.getConstructor(new Class[] {});

     //对象

     Object dexSlave=constructor.newInstance(new Object[]{});

     //方法

     Method sayHello=mLoadClass.getDeclareMethod("sayHello",new Class[]{});

     //方法属性

     sayHello.setAccessible(true);

     //调用方法

     sayHello.invoke(dexSlave,new Object[]{});

}catch…


ClassLoader localClassLoader=ClassLoader.getSystemClassLoader();

DexClassLoader localDexClassLoader=new DexClassLoader(dexpath,dexOutputPath,null,localClassLoader);

try{

     …

//args代表传递给方法的参数,receiver表示哪个对象上调用该方法

public Object invoke (Object receiver, Object… args)


dalvik.system.DexFile也可以动态加载dex文件,但是它只能被VM调用。

因为:DexFile的构造器中,要在/data/dalvik-cache目录下生成dex文件,但是普通应用程序没有对该目录的写权限。


对被调用的.apk .jar文件可以采取以下措施保护:


JNI方式动态加载:

     static void com_mtn_javainject_CopyFile_callHook(JNIEnv *env, jclass,jstring path1, jstring path2, jstring className, jstring methodName){

          //找到ClassLoader

               jclass  classLoaderClass=env->FindClass("java/lang/ClassLoader");

               //找到ClassLoader的静态方法getSystemClassLoader

               jMethodID getsysLoaderMethod=env->GetStaticMethodID(classLoaderClass,"getSystemClassLoader","()Ljava/lang/ClassLoader:");

               //调用getSystemClassLoader方法,返回ClassLoader对象

               jobject loader=env->CallStaticObjectMethod(classLoaderClass,getsysLoaderMethod);

               //jar包存放位置

               jstring dexpath=path1;

               //优化后的jar包存放位置

               jstring dex_odex_path=path2;     

               //找到DexClassLoader类

               jclass dexLoaderClass=env->FindClass("dalvik/system/DexClassLoader");

               //获取DexClassLoader的构造函数ID

               jmethodID initDexLoaderMethod=env->GetMethodIDdexLoaderClass,"",(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader:)V");

               //新建一个DexClassLoader对象

               jobject  dexLoader=env->NewObject(dexLoaderClass,initDexLoaderMethod,dexpath,dex_odex_path,NULL,loader);

               //找到DexClassLoader中的findClass()方法

               jmethodID findClassMethod=env->GetMethodID(dexLoaderClass,"findClass","(Ljava/lang/String;)Ljava/lang/Class;");

               //如果返回空,则找DexClassLoader的loadClass()方法--新版本SDK中

               if(NULL==findClassMethod){

                    findClassMethod=env->GetMethodID(dexClassLoader,"loadClass","(Ljava/lang/String;)Ljava/lang/Class;");

               }

               //存储需要调用的类,传入进来的

               jstring javaClassName=className;

               //调用DexClassLoader方法,加载需要调用的类

               jclass javaClientClass=(jclass)env->CallObjectMethod(dexLoader,findClassMethod,javaClassName);

               //将jstring类型的方法名转换为utf-8编码的字符串,methodName是传进来的

               const  char *func=env->GetStringUFTChars(methodName,NULL);

               //获取加载的类中的方法

               jmethodID inject_method=env->GetStaticMethodID(javaClientClass,func,"()V");

               //调用加载的类中的静态方法

               env->CallStaticVoidMethod(javaClientClass,inject_method);

}