stub包
若干年前,我用eclipse开发安卓,反编译jar的时候发现android.jar内部的东西,所有方法都只有一个实现:
throw new RuntimeException("Stub!");
当时我还只会写几个activity,完全是懵逼状态,这样的实现到底能干什么?
后来查阅了一系列资料,明白了这个jar只是用于编译的,程序打包成apk的时候并不会把这个jar打进去,而编译时只需要类结构并不需要管里面的实现,当然,我们并不会去在电脑上实际运行它。
那么到了实际运行时这些类是如何获取的呢?我觉得,真正具有完整实现的android.jar里面的东西当然在安卓设备里,让我们验证一下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ClassLoader classLoader = getClass().getClassLoader();
while (classLoader != null){
Log.e("classloader",classLoader.getClass().getName());
classLoader = classLoader.getParent();
}
try {
Class activityThreadClass = Class.forName("android.app.ActivityThread");
Log.e("classloader",String.format("ActivityThread is loaded by %s", activityThreadClass.getClassLoader()));
Log.e("classloader",String.format("Handler is loaded by %s", Handler.class.getClassLoader()));
Log.e("classloader",String.format("MainActivity is loaded by %s", getClass().getClassLoader()));
Log.e("classloader",String.format("Application is loaded by %s", getApplication().getClass().getClassLoader()));
Log.e("classloader",String.format("CommonTabLayout is loaded by %s", CommonTabLayout.class.getClassLoader()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
以上代码,先循环取父加载器,看系统中有几种java类加载器,然后分别取了我们自定义的类、第三方库的类、系统类进行输入看是哪种类加载器加载的它。输出结果如下:
输出结果
可以看到,系统类是由BootClassLoader预先加载的,第三方库的类(打到了apk包里)和我们自定义的类(也在apk里)是由PathClassLoader加载的。当然,类加载器在jni层还有其他的,我们用java代码访问不到而已。
我们程序在用到系统类的时候,根据类加载器的双亲委派模式,向上查找,由BootClassLoader返回预先加载的类供我们使用,这里的类已经不是stub实现的假类了。