22回答

3收藏

Android逆向之ClassLoader loadClass java层源码查看

信息分享 信息分享 16239 人阅读 | 22 人回复 | 2019-12-10


不管是 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;



[ttreply]

总结:

loadClass(ClassLoader.java) -> findClass(BaseDexClassLoader.java) -> findClass(DexPathList.java) ->

findClass(DexPathList.java -> Element -> findClass) -> loadClassBinaryName(DexFile.java) ->

defineClass(DexFile.java) -> defineClassNative(DexFile.java) -> Native层

[/ttreply]




欢迎关注我的公众号【妄为写代码】,一起交流学习





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
分享到:
回复

使用道具 举报

回答|共 22 个

zhaoboy666

发表于 2019-12-10 11:44:54 | 显示全部楼层

牛皮666
回复

使用道具 举报

山那边的瘦子

发表于 2019-12-10 11:51:00 | 显示全部楼层

花哥牛皮
回复

使用道具 举报

only

发表于 2019-12-10 11:56:36 | 显示全部楼层

优秀 加油
回复

使用道具 举报

Shamrock

发表于 2019-12-10 11:58:10 | 显示全部楼层

花哥牛皮
回复

使用道具 举报

Henryhaohao

发表于 2019-12-10 13:24:36 | 显示全部楼层

666厉害
回复

使用道具 举报

all_spider

发表于 2019-12-10 14:23:56 | 显示全部楼层

大佬
回复

使用道具 举报

萌木盖

发表于 2019-12-10 14:30:10 | 显示全部楼层

回复

使用道具 举报

花儿谢了

发表于 2019-12-10 14:31:43 | 显示全部楼层

你还敢发言,我看你早晚被公司抓到
回复

使用道具 举报

chendipang

发表于 2019-12-10 14:41:20 | 显示全部楼层

666
回复

使用道具 举报