加壳相关

JVM里面三种类加载器
bootstrap classloader
extensions classloader
application classloader
系统中加载顺序也是如上
也可以自定义类加载器
委托关系
先看图

还是很够吧形象的

这种双亲委派好处有俩
避免重复加载
避免类似于想恶意dll注入这种自己实现某个类导致系统本身类不被加载
双亲委派关键 表示父节点

加载时机
隐式加载
创建类的实例
访问类的静态变量或者为静态变量赋值
调用类的静态方法
使用反射方式强制创建某个类或接口对应的java.lang.Class对象
初始化某个类的子类
显示加载
使用LoadClass
使用forname加载
来粗浅看一下如何加载class的
加载
查找和导入这个class文件
链接
检查 检查导入的class文件的正确性
准备 给类的静态变量分配存储空间
解析 把符号引用转成直接引用
初始化
调用 clinit 函数 将静态变量 静态代码块做初始化操作

安卓中 一些classloader的继承图

很不错啊

上面这八个 calssloader为抽象类
basedexclassloader与加脱壳紧密相关 其中的pathclassloader是Android默认的类加载器
dexclassloader也是重点
pathclassloader 四大组件要通过这个加载
dexclassloader
http://aospxref.com/android-8.0.0_r36/xref/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java
http://aospxref.com/android-8.0.0_r36/xref/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java
http://aospxref.com/android-8.0.0_r36/xref/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java#30
http://aospxref.com/android-8.0.0_r36/xref/libcore/dalvik/src/main/java/dalvik/system/InMemoryDexClassLoader.java
http://aospxref.com/android-8.0.0_r36/xref/libcore/ojluni/src/main/java/java/lang/ClassLoader.java#180
注释写的非常好
如

parenet是什么时候给的 拿inmemorydexclassloader举例

回到baseclassloader

回到classloader 到咯

哈哈哈哈自己写了一个demo看看这个mainactivity以及他的parent是谁
package com.example.kanxue12;
import android.os.Bundle;
import android.util.Log;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
testClassLoader();
}
public void testClassLoader(){
ClassLoader thisClassLoader = MainActivity.class.getClassLoader();
Log.i("kanxue","thisClassLoader"+thisClassLoader);
ClassLoader tmpClassLoader=null;
ClassLoader parentClassLoader=thisClassLoader.getParent();
while(parentClassLoader!=null){
Log.i("kanxue","this:"+thisClassLoader+"-----"+parentClassLoader);
thisClassLoader = parentClassLoader;
parentClassLoader = tmpClassLoader;
}
Log.i("kanxue","root"+thisClassLoader);
}
}
日志输出的
kanxue com.example.kanxue12 I thisClassLoaderdalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.kanxue12-SIKDTDOcNa_tqDC7e59_RA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.kanxue12-SIKDTDOcNa_tqDC7e59_RA==/lib/arm64, /system/lib64, /vendor/lib64]]]
1970-02-28 14:36:28.646 20586-20586 kanxue com.example.kanxue12 I this:dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.kanxue12-SIKDTDOcNa_tqDC7e59_RA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.kanxue12-SIKDTDOcNa_tqDC7e59_RA==/lib/arm64, /system/lib64, /vendor/lib64]]]-----java.lang.BootClassLoader@eece960
1970-02-28 14:36:28.646 20586-20586 kanxue com.example.kanxue12 I rootjava.lang.BootClassLoader@eece960
可以看到就很简单哈 pathclassloader-bootclassloader

好下一个 通过dexclassloader加载sdcard里面的dex
编译一个dex放进去,dex里面函数就是这样

给主app权限

方法这么些
package com.example.kanxue122;
import android.content.Context;
import android.os.Bundle;
import java.lang.Object;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import dalvik.system.DexClassLoader;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
Context appContext = this.getApplicationContext();
try {
testDexClassLoader(appContext,"/sdcard/classes3.dex");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public void testDexClassLoader(Context context,String dexfilepath) throws ClassNotFoundException {
File optfile = context.getDir("opt_dex",0);
File libfile = context.getDir("lib_path",0);
ClassLoader parentClassLoader = MainActivity.class.getClassLoader();
DexClassLoader dexClassLoader = new DexClassLoader(dexfilepath,optfile.getAbsolutePath(), libfile.getAbsolutePath(), MainActivity.class.getClassLoader());
Class<?> clazz=null;
try {
clazz=dexClassLoader.loadClass("com.example.kanxue12.test");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(clazz!=null){
try {
Method testFunctionMethod = clazz.getDeclaredMethod("test1");
Object obj = clazz.newInstance();
testFunctionMethod.invoke(obj);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
反射调用dex里面的方法 成功

实现动态加载
