Let’s start with loading our APK into ClassyShark, I will use the Chrome APK as an example here. Once you have opened ClassyShark and loaded the APK you will see something like this:
Great, now if we click on the APK name from the tree we see this data:
Let’s take a look at what this data represents, we see one dex file with its native and abstract methods counts, followed by the breakdown of the native libs. Remember that your APK can contain more than one dex. Multidex would be the most common reason to do that.
Which class will end up in which dex file is defined by the rules found here. However, the situation is trickier when we are looking at native methods. The main caveat is that the native code can be dynamically loaded at runtime. Calling a native method that lives in the library that hasn’t been loaded yet will make your app crash.
Another caveat is, calling from native methods unloaded Java code (from secondary dexes). This will crash your app. The rule is, call the MultiDex.install first. Make sure there are no native calls (both Java → native and native → Java) before the MultiDex.install is called.
ClassyShark is the only tool that can give you the precise picture of which method goes to which classes.dex. It is pretty easy to view the contents of a dex file by just clicking on it in the list.
When dealing with native libraries, ClassyShark can help you track down the issues of various nature, including checking quickly, if you are missing a specific library for a certain architecture.