Java /Android 默认ClassLoader是PathClassLoader
Android 的 PathClassLoader 和DexClassLoader 都是BaseDexClassLoader的子类
BaseClassLoader是ClassLoader的子类,通过loadClass方法加载,Android将Java的ClassLoader简化了,第二个参数arg2 无效
loadClass 通过 findLoadedClass 方法进行查找,先查找缓存,缓存有就返回,否则就
查找父Loader,如果父加载器没有,就执行 findBootstrapClassOrNull()//空方法
如果都找不到就执行findClass找,自己加载
缓存时独立共享的内存
BaseDexClassLoader
findClass:
pathList = DexPathList
@Override
203 protected Class> findClass(String name) throws ClassNotFoundException {
204 // First, check whether the class is present in our shared libraries.
205 if (sharedLibraryLoaders != null) {
206 for (ClassLoader loader : sharedLibraryLoaders) {
207 try {
208 return loader.loadClass(name);
209 } catch (ClassNotFoundException ignored) {
210 }
211 }
212 }
213 // Check whether the class in question is present in the dexPath that
214 // this classloader operates on.
215 List suppressedExceptions = new ArrayList();
216 Class c = pathList.findClass(name, suppressedExceptions);
217 if (c == null) {
218 ClassNotFoundException cnfe = new ClassNotFoundException(
219 "Didn't find class \"" + name + "\" on path: " + pathList);
220 for (Throwable t : suppressedExceptions) {
221 cnfe.addSuppressed(t);
222 }
223 throw cnfe;
224 }
225 return c;
226 }
主要通过pathList.findClass(name,suppressedExecption) 查找
pathList.findClass
public Class> findClass(String name, List suppressed) {
531 for (Element element : dexElements) {
532 Class> clazz = element.findClass(name, definingContext, suppressed);
533 if (clazz != null) {
534 return clazz;
535 }
536 }
537
538 if (dexElementsSuppressedExceptions != null) {
539 suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
540 }
541 return null;
542 }
通过Element.-dexFile.-loadClass-,defindClass-native
split() -------- Unix系统分割使用 : ,Window使用 ;
new DexClassLoader时可以("path1:path2:path3:path4:path5:path6")
Element[] nakeDexElements(){
for(File file : files){
//添加
}
}
private static Element[] makeDexElements(List files, File optimizedDirectory,
369 List suppressedExceptions, ClassLoader loader, boolean isTrusted) {
370 Element[] elements = new Element[files.size()];
371 int elementsPos = 0;
372 /*
373 * Open all files and load the (direct or contained) dex files up front.
374 */
375 for (File file : files) {
376 if (file.isDirectory()) {
377 // We support directories for looking up resources. Looking up resources in
378 // directories is useful for running libcore tests.
379 elements[elementsPos++] = new Element(file);
380 } else if (file.isFile()) {
381 String name = file.getName();
382
383 DexFile dex = null;
384 if (name.endsWith(DEX_SUFFIX)) { //如果是.dex
385 // Raw dex file (not inside a zip/jar).
386 try {
387 dex = loadDexFile(file, optimizedDirectory, loader, elements);
388 if (dex != null) {
389 elements[elementsPos++] = new Element(dex, null);
390 }
391 } catch (IOException suppressed) {
392 System.logE("Unable to load dex file: " + file, suppressed);
393 suppressedExceptions.add(suppressed);
394 }
395 } else {
396 try {
397 dex = loadDexFile(file, optimizedDirectory, loader, elements);
398 } catch (IOException suppressed) {
399 /*
400 * IOException might get thrown "legitimately" by the DexFile constructor if
401 * the zip file turns out to be resource-only (that is, no classes.dex file
402 * in it).
403 * Let dex == null and hang on to the exception to add to the tea-leaves for
404 * when findClass returns null.
405 */
406 suppressedExceptions.add(suppressed);
407 }
408
409 if (dex == null) {
410 elements[elementsPos++] = new Element(file);
411 } else {
412 elements[elementsPos++] = new Element(dex, file);
413 }
414 }
415 if (dex != null && isTrusted) {
416 dex.setTrusted();
417 }
418 } else {
419 System.logW("ClassLoader referenced unknown path: " + file);
420 }
421 }
422 if (elementsPos != elements.length) {
423 elements = Arrays.copyOf(elements, elementsPos);
424 }
425 return elements;
426 }
427
OKHttp 下载文件
自动打包补丁:
还可以通过修改字节码实现热更新