java - Is it necessary to keep classes of the same package in the same dex while using multiple dex files -


about title

"classes of same package" means classes share same package access. please pay attention fact class a.b.c.foo doesn't have package access class a.b.bar . because latter can't access former if former's modifier default.

problem

if split 2 classes in same packages 2 dex files, though load them correctly, error while running, logcat likes:

i/dalvikvm( 6498): dexopt: illegal method access (call lcom/fish47/multidex/foo;.iswholeword (lcom/fish47/multidex/foo;)z lcom/fish47/multidex/testmatchword;)
i/dalvikvm( 6498): not find method com.fish47.multidex.core.foo.iswholeword, referenced method com.fish47.multidex.core.testmatchword.test_english
w/dalvikvm( 6498): vfy: unable resolve virtual method 758: lcom/fish47/multidex/foo;.iswholeword (lcom/fish47/multidex/foo;)z


conjecture

that's code pop out error message below:
vm/analysis/optimize.c ==> line: 697 - 714

/* access allowed? */ tweakloader(referrer, resmethod->clazz); bool allowed = dvmcheckmethodaccess(referrer, resmethod); untweakloader(referrer, resmethod->clazz); if (!allowed) {     if_logi() {         char* desc = dexprotocopymethoddescriptor(&resmethod->prototype);         logi("dexopt: illegal method access (call %s.%s %s %s)\n",             resmethod->clazz->descriptor, resmethod->name, desc,             referrer->descriptor);         free(desc);     }     if (pfailure != null)         *pfailure = verify_error_access_method;     return null; } 


pay attention value of resclass->classloader . if 2 classes aren't same dex file, value set 0xdead3333.
vm/analysis/optimize.c ==> line: 285 - 299

static void tweakloader(classobject* referrer, classobject* resclass) {     if (!gdvm.optimizing)         return;     assert(referrer->classloader == null);     assert(resclass->classloader == null);      if (!gdvm.optimizingbootstrapclass) {         /* class loader array class comes element type */         if (dvmisarrayclass(resclass))             resclass = resclass->elementclass;         if (referrer->pdvmdex != resclass->pdvmdex)             resclass->classloader = (object*) 0xdead3333;     } } 


this trick, lets checkaccess(...) method return false @ last, if 2 classes in same package, accessible each other not public.
vm/oo/accesscheck.c ==> line: 88 - 116

static bool checkaccess(const classobject* accessfrom,     const classobject* accessto, u4 accessflags) {     /* quick accept public access */     if (accessflags & acc_public)         return true;      /* quick accept access same class */     if (accessfrom == accessto)         return true;      /* quick reject private access class */     if (accessflags & acc_private)         return false;      /*      * semi-quick test protected access sub-class, may or      * may not in same package.      */     if (accessflags & acc_protected)         if (dvmissubclass(accessfrom, accessto))             return true;      /*      * allow protected , private access other classes in same      * package.      */     return dvminsamepackage(accessfrom, accessto); } 

vm/oo/accesscheck.c ==> line: 39 - 83

bool dvminsamepackage(const classobject* class1, const classobject* class2) {     ...      /* class loaders must match */     if (class1->classloader != class2->classloader)         return false;      ... }  

this strange area, owing largely "pre-verification" , optimization performed dexopt. background, should read comments @ start of oo/class.cpp (lines 39-153).

(note: files changed ".c" ".cpp" in ics. should examining current sources, though in practice little has changed here in last few years.)

generally speaking, 2 classes in same package in different dex files able access each other package scope long both dex files loaded same class loader. that's checks in accesscheck.cpp enforce.

what you're looking @ in optimize.cpp parallel implementation of resolver -- dvmoptresolveclass vs. dvmresolveclass -- used during verification , optimization. tweak class loader noted, only if it's running inside dexopt (that's check against !gdvm.optimizing means). if it's inside normally-executing vm instance, loader not tweaked during checks.

when running part of dexopt, code in optimize.cpp either verifying+optimizing bootstrap classes, or verifying+optimizing single non-bootstrap dex file. either way, of dex files loaded through bootstrap loader, because vm isn't running , it's way load classes. (the point of dexopt verify many classes possible @ build or install time don't have @ app startup time. read more dexopt here.)

the code in tweakloader says: if i'm in dexopt, , i'm not optimizing actual bootstrap dex file (e.g. framework.jar), need make sure package-scope checks assume classes in current dex file not being loaded bootstrap class loader.

for example, create class called java.lang.stuff in app. in dexopt, because loaded single loader, able touch package-private stuff in other java.lang classes if didn't tweak loader. when app run, java.lang classes come bootstrap loader , stuff class comes app loader, accesses should forbidden.

so that's code does. far specific issue goes, i'd expect calls work long same loader used load both dex files. if 1 dex loaded app framework , other custom dexclassloader wouldn't expect work.

one additional note: errors pasted in mention both com.fish47.multidex.foo , com.fish47.multidex.core.foo, aren't same package. don't know if that's related. also, if there additional vfy messages it's include those, if they're bit unintelligible. , of nature it's important specify version of android you're using -- hasn't changed in while, if go far enough it's different.


Comments

Popular posts from this blog

assembly - 8086 TASM: Illegal Indexing Mode -

Java, LWJGL, OpenGL 1.1, decoding BufferedImage to Bytebuffer and binding to OpenGL across classes -

javascript - addthis share facebook and google+ url -