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 Slide

  2. ClassLoader

    View Slide

  3. class ClassLoader

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  11. Class> loadClass(String name)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  15. View Slide

  16. class PathClassLoader

    View Slide

  17. class PathClassLoader
    class DexClassLoader

    View Slide

  18. class PathClassLoader extends BaseDexClassLoader
    class DexClassLoader extends BaseDexClassLoader

    View Slide

  19. class BaseDexClassLoader {a
    DexPathList pathList
    }a

    View Slide

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

    View Slide

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

    View Slide

  22. Story time!

    View Slide

  23. View Slide

  24. View Slide

  25. View Slide

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

    View Slide

  27. class CustomClassLoader extends PathClassLoader

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  37. View Slide

  38. BlackM
    irro
    r

    View Slide

  39. Demo time!

    View Slide

  40. github.com/hzsweers/
    blackmirror

    View Slide

  41. Final notes

    View Slide

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

    View Slide

  43. Be mindful

    View Slide

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

    View Slide