Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Breaking the Android ClassLoader

Breaking the Android ClassLoader

ClassLoaders are not new. They've existed since Java 1.0 and are a core part of how the JVM works. Things work a bit different under the hood in Android, but the core principles are the same and we, as Android developers, largely take it for granted. This talk will be a deep dive into how class loading works in Android and later explore the implications of trying to manipulate the application's ClassLoader at runtime (for better or worse 🔥) in the context of logging, hot fixing, adding features, and interacting with 3rd party code.

Sample project: https://github.com/hzsweers/blackmirror

Zac Sweers

August 28, 2018
Tweet

More Decks by Zac Sweers

Other Decks in Programming

Transcript

  1. Breaking the
    Android ClassLoader
    Zac Sweers
    @pandanomic
    Photo by Vitalis Hirschmann on Unsplash

    View full-size slide

  2. class ClassLoader

    View full-size slide

  3. class ClassLoader {a
    Class> loadClass(String name);
    Class> findClass(String name);
    Class> defineClass(...);
    URL getResource(String name);
    // A few others
    }a

    View full-size slide

  4. class ClassLoader {a
    Class> loadClass(String name);
    Class> findClass(String name);
    Class> defineClass(...);
    URL getResource(String name);
    // A few others
    }a

    View full-size slide

  5. class URLClassLoader {a
    Class> loadClass(String name) {
    // Go fetch them from a jar
    }a
    }a

    View full-size slide

  6. class URLClassLoader {a
    Class> loadClass(String name) {
    // Go fetch them from a jar
    }a
    }a

    View full-size slide

  7. class URLClassLoader {a
    Class> loadClass(String name) {
    // Go fetch them from a jar
    }a
    }a

    View full-size slide

  8. class URLClassLoader {a
    // ClassLoader parent
    Class> loadClass(String name)
    }a

    View full-size slide

  9. class URLClassLoader {a
    // ClassLoader parent
    Class> loadClass(String name)
    }a

    View full-size slide

  10. Class> loadClass(String name)

    View full-size slide

  11. package example;
    class Foo {
    private Bar bar;
    }a

    View full-size slide

  12. package example;
    class Foo {
    private Bar bar;
    }a
    loadClass("example.Foo")

    View full-size slide

  13. package example;
    class Foo {
    private Bar bar;
    }a
    loadClass("example.Foo")
    Foo.class.getClassLoader().loadClass("example.Bar")

    View full-size slide

  14. class PathClassLoader

    View full-size slide

  15. class PathClassLoader
    class DexClassLoader

    View full-size slide

  16. class PathClassLoader extends BaseDexClassLoader
    class DexClassLoader extends BaseDexClassLoader

    View full-size slide

  17. class BaseDexClassLoader {a
    DexPathList pathList
    }a

    View full-size slide

  18. class BaseDexClassLoader {a
    DexPathList pathList
    // --> DexFile, etc
    }a

    View full-size slide

  19. class BaseDexClassLoader {a
    DexPathList pathList
    // --> DexFile, etc
    }a

    View full-size slide

  20. PathClassLoader classLoader = new PathClassLoader(
    context.getApplicationInfo().sourceDir,
    /* parent */ null
    );

    View full-size slide

  21. class CustomClassLoader extends PathClassLoader

    View full-size slide

  22. class CustomClassLoader extends PathClassLoader {
    @Override public Class> loadClass(String name) {
    Log.d("ClLoading", "Loading " + name);
    return super.loadClass(name);
    }
    }

    View full-size slide

  23. CustomClassLoader cl = new CustomClassLoader(...);

    View full-size slide

  24. CustomClassLoader cl = new CustomClassLoader(...);
    // set java.lang.ClassLoader$SystemClassLoader.loader

    View full-size slide

  25. CustomClassLoader cl = new CustomClassLoader(...);
    // set java.lang.ClassLoader$SystemClassLoader.loader
    Thread.currentThread().setContextClassLoader(cl)

    View full-size slide

  26. CustomClassLoader cl = new CustomClassLoader(...);
    // set java.lang.ClassLoader$SystemClassLoader.loader
    Thread.currentThread().setContextClassLoader(cl)
    ContextImpl

    View full-size slide

  27. CustomClassLoader cl = new CustomClassLoader(...);
    // set java.lang.ClassLoader$SystemClassLoader.loader
    Thread.currentThread().setContextClassLoader(cl)
    ContextImpl.mClassLoader

    View full-size slide

  28. CustomClassLoader cl = new CustomClassLoader(...);
    // set java.lang.ClassLoader$SystemClassLoader.loader
    Thread.currentThread().setContextClassLoader(cl)
    ContextImpl

    View full-size slide

  29. CustomClassLoader cl = new CustomClassLoader(...);
    // set java.lang.ClassLoader$SystemClassLoader.loader
    Thread.currentThread().setContextClassLoader(cl)
    ContextImpl.mPackageInfo

    View full-size slide

  30. CustomClassLoader cl = new CustomClassLoader(...);
    // set java.lang.ClassLoader$SystemClassLoader.loader
    Thread.currentThread().setContextClassLoader(cl)
    ContextImpl.mPackageInfo.mClassLoader

    View full-size slide

  31. github.com/hzsweers/
    blackmirror

    View full-size slide

  32. Harder in Pie
    g.co/dev/appcompat

    View full-size slide

  33. github.com/hzsweers/
    blackmirror
    Zac Sweers
    @pandanomic

    View full-size slide