ClassLoader loadClass java层源码查看
不管是 fdex2 脱壳的核心思想,还是 Android 的热修复技术等,当中都有 loadClass 的身影。
java类装载:
ClassLoader loadClass:默认情况下,只加载目标类,并不进行链接和初始化
Class.forName: 默认情况下,加载目标类,如果类之前没有被初始化,则会进行类的初始化,主要体现在静态区域的初始化
libcore/ojluni/src/main/java/java/lang/ClassLoader.java
双亲委派机制加载类,如果双亲未加载且无法加载目标类,则调用 findClass 去加载,此方法由子类实现
public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. c = findClass(name); } } return c; } protected Class<?> findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); }
libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
public class BaseDexClassLoader extends ClassLoader { /** * Hook for customizing how dex files loads are reported. * * This enables the framework to monitor the use of dex files. The * goal is to simplify the mechanism for optimizing foreign dex files and * enable further optimizations of secondary dex files. * * The reporting happens only when new instances of BaseDexClassLoader * are constructed and will be active only after this field is set with * {@link BaseDexClassLoader#setReporter}. */ /* @NonNull */ private static volatile Reporter reporter = null; private final DexPathList pathList; @Override protected Class<?> findClass(String name) throws ClassNotFoundException { List<Throwable> suppressedExceptions = new ArrayList<Throwable>(); Class c = pathList.findClass(name, suppressedExceptions); if (c == null) { ClassNotFoundException cnfe = new ClassNotFoundException( "Didn't find class \"" + name + "\" on path: " + pathList); for (Throwable t : suppressedExceptions) { cnfe.addSuppressed(t); } throw cnfe; } return c; } }
libcore/dalvik/src/main/java/dalvik/system/DexPathList.java
public Class<?> findClass(String name, List<Throwable> suppressed) { for (Element element : dexElements) { Class<?> clazz = element.findClass(name, definingContext, suppressed); if (clazz != null) { return clazz; } } if (dexElementsSuppressedExceptions != null) { suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions)); } return null; } private Element[] dexElements; this.dexElements = makeInMemoryDexElements(dexFiles, suppressedExceptions); private static Element[] makeInMemoryDexElements(ByteBuffer[] dexFiles, List<IOException> suppressedExceptions) { Element[] elements = new Element[dexFiles.length]; int elementPos = 0; for (ByteBuffer buf : dexFiles) { try { DexFile dex = new DexFile(buf); elements[elementPos++] = new Element(dex); } catch (IOException suppressed) { System.logE("Unable to load dex file: " + buf, suppressed); suppressedExceptions.add(suppressed); } } if (elementPos != elements.length) { elements = Arrays.copyOf(elements, elementPos); } return elements; } /*package*/ static class Element { /** * A file denoting a zip file (in case of a resource jar or a dex jar), or a directory * (only when dexFile is null). */ private final File path; private final DexFile dexFile; private ClassPathURLStreamHandler urlHandler; private boolean initialized; /** * Element encapsulates a dex file. This may be a plain dex file (in which case dexZipPath * should be null), or a jar (in which case dexZipPath should denote the zip file). */ public Element(DexFile dexFile, File dexZipPath) { this.dexFile = dexFile; this.path = dexZipPath; } public Class<?> findClass(String name, ClassLoader definingContext, List<Throwable> suppressed) { return dexFile != null ? dexFile.loadClassBinaryName(name, definingContext, suppressed) : null; } }
libcore/dalvik/src/main/java/dalvik/system/DexFile.java
public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed) { return defineClass(name, loader, mCookie, this, suppressed); } private static Class defineClass(String name, ClassLoader loader, Object cookie, DexFile dexFile, List<Throwable> suppressed) { Class result = null; try { result = defineClassNative(name, loader, cookie, dexFile); } catch (NoClassDefFoundError e) { if (suppressed != null) { suppressed.add(e); } } catch (ClassNotFoundException e) { if (suppressed != null) { suppressed.add(e); } } return result; } private static native Class defineClassNative(String name, ClassLoader loader, Object cookie, DexFile dexFile) throws ClassNotFoundException, NoClassDefFoundError;
总结:
loadClass(ClassLoader.java) -> findClass(BaseDexClassLoader.java) -> findClass(DexPathList.java) ->
findClass(DexPathList.java -> Element -> findClass) -> loadClassBinaryName(DexFile.java) ->
defineClass(DexFile.java) -> defineClassNative(DexFile.java) -> Native层
- 点赞
- 收藏
- 关注作者
评论(0)