This is a somewhat strange area, mainly due to the “pre-validation” and optimization performed by dexopt. For the background, you should read the comments at the beginning of oo / Class.cpp (lines 39-153).
(Note: the files were changed from “.c” to “.cpp” in ICS. You should probably look at current sources, although in practice there has been little change in the last few years.)
Generally speaking, two classes in the same package in different DEX files could access each other with the package area if both DEX files are loaded by the same class loader. This is what was tested in AccessCheck.cpp.
What you are looking for in Optimize.cpp is a parallel converter implementation - dvmOptResolveClass vs. dvmResolveClass - which is used during validation and optimization. It will configure the class loader, as you noted, but only if it works inside dexopt (which means checking with !gDvm.optimizing ). If it is inside a normally executable instance of a virtual machine, the bootloader will not be changed during the checks.
When launched as part of dexopt, the code in Optimize.cpp either checks + optimizes the boot classes, or checks + optimizes a single DEX file without loading. In any case, all DEX files are loaded through the bootloader because the virtual machine is not working, and this is the only way to load classes. (The dexopt point should check as many classes as possible during assembly or installation, so we don’t need to do this when the application starts. More about dexopt here .)
The code in tweakLoader says: if I am in dexopt and I am not optimizing the actual DEX file for initial loading (e.g. framework.jar), then I need to make sure that the package scope checks assume that the classes in the current DEX file are not loaded by the class loader bootstrap.
For example, I could create a class called java.lang.Stuff in my application. In dexopt, since everything is loaded with a single loader, it will be able to touch the package-private material in other java.lang classes if we do not select the loader. When the application actually runs, the java.lang classes are taken from the boot loader, and the Stuff class comes from the application loader, so these calls should be prohibited.
So what the code does. As for your specific problem, I expect the calls to work as long as the same bootloader is used to load both DEX files. If one DEX is loaded with application infrastructure and the other with custom DexClassLoader , then I did not expect it to work.
One more note: the errors you inserted mention both com.fish47.multidex.Foo and com.fish47.multidex.core.Foo , which are not the same package. I do not know if this is related. In addition, if there are additional VFY messages, it is useful to include them, even if they are a little incomprehensible. And for whatever it is, it’s also important to indicate which version of Android you are using - it has not changed after a while, but if you come back far enough, it’s completely different.