Home | History | Annotate | Download | only in oo
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Resolve classes, methods, fields, and strings.
     19  *
     20  * According to the VM spec (v2 5.5), classes may be initialized by use
     21  * of the "new", "getstatic", "putstatic", or "invokestatic" instructions.
     22  * If we are resolving a static method or static field, we make the
     23  * initialization check here.
     24  *
     25  * (NOTE: the verifier has its own resolve functions, which can be invoked
     26  * if a class isn't pre-verified.  Those functions must not update the
     27  * "resolved stuff" tables for static fields and methods, because they do
     28  * not perform initialization.)
     29  */
     30 #include "Dalvik.h"
     31 
     32 #include <stdlib.h>
     33 
     34 
     35 /*
     36  * Find the class corresponding to "classIdx", which maps to a class name
     37  * string.  It might be in the same DEX file as "referrer", in a different
     38  * DEX file, generated by a class loader, or generated by the VM (e.g.
     39  * array classes).
     40  *
     41  * Because the DexTypeId is associated with the referring class' DEX file,
     42  * we may have to resolve the same class more than once if it's referred
     43  * to from classes in multiple DEX files.  This is a necessary property for
     44  * DEX files associated with different class loaders.
     45  *
     46  * We cache a copy of the lookup in the DexFile's "resolved class" table,
     47  * so future references to "classIdx" are faster.
     48  *
     49  * Note that "referrer" may be in the process of being linked.
     50  *
     51  * Traditional VMs might do access checks here, but in Dalvik the class
     52  * "constant pool" is shared between all classes in the DEX file.  We rely
     53  * on the verifier to do the checks for us.
     54  *
     55  * Does not initialize the class.
     56  *
     57  * "fromUnverifiedConstant" should only be set if this call is the direct
     58  * result of executing a "const-class" or "instance-of" instruction, which
     59  * use class constants not resolved by the bytecode verifier.
     60  *
     61  * Returns NULL with an exception raised on failure.
     62  */
     63 ClassObject* dvmResolveClass(const ClassObject* referrer, u4 classIdx,
     64     bool fromUnverifiedConstant)
     65 {
     66     DvmDex* pDvmDex = referrer->pDvmDex;
     67     ClassObject* resClass;
     68     const char* className;
     69 
     70     /*
     71      * Check the table first -- this gets called from the other "resolve"
     72      * methods.
     73      */
     74     resClass = dvmDexGetResolvedClass(pDvmDex, classIdx);
     75     if (resClass != NULL)
     76         return resClass;
     77 
     78     LOGVV("--- resolving class %u (referrer=%s cl=%p)\n",
     79         classIdx, referrer->descriptor, referrer->classLoader);
     80 
     81     /*
     82      * Class hasn't been loaded yet, or is in the process of being loaded
     83      * and initialized now.  Try to get a copy.  If we find one, put the
     84      * pointer in the DexTypeId.  There isn't a race condition here --
     85      * 32-bit writes are guaranteed atomic on all target platforms.  Worst
     86      * case we have two threads storing the same value.
     87      *
     88      * If this is an array class, we'll generate it here.
     89      */
     90     className = dexStringByTypeIdx(pDvmDex->pDexFile, classIdx);
     91     if (className[0] != '\0' && className[1] == '\0') {
     92         /* primitive type */
     93         resClass = dvmFindPrimitiveClass(className[0]);
     94     } else {
     95         resClass = dvmFindClassNoInit(className, referrer->classLoader);
     96     }
     97 
     98     if (resClass != NULL) {
     99         /*
    100          * If the referrer was pre-verified, the resolved class must come
    101          * from the same DEX or from a bootstrap class.  The pre-verifier
    102          * makes assumptions that could be invalidated by a wacky class
    103          * loader.  (See the notes at the top of oo/Class.c.)
    104          *
    105          * The verifier does *not* fail a class for using a const-class
    106          * or instance-of instruction referring to an unresolveable class,
    107          * because the result of the instruction is simply a Class object
    108          * or boolean -- there's no need to resolve the class object during
    109          * verification.  Instance field and virtual method accesses can
    110          * break dangerously if we get the wrong class, but const-class and
    111          * instance-of are only interesting at execution time.  So, if we
    112          * we got here as part of executing one of the "unverified class"
    113          * instructions, we skip the additional check.
    114          *
    115          * Ditto for class references from annotations and exception
    116          * handler lists.
    117          */
    118         if (!fromUnverifiedConstant &&
    119             IS_CLASS_FLAG_SET(referrer, CLASS_ISPREVERIFIED))
    120         {
    121             ClassObject* resClassCheck = resClass;
    122             if (dvmIsArrayClass(resClassCheck))
    123                 resClassCheck = resClassCheck->elementClass;
    124 
    125             if (referrer->pDvmDex != resClassCheck->pDvmDex &&
    126                 resClassCheck->classLoader != NULL)
    127             {
    128                 LOGW("Class resolved by unexpected DEX:"
    129                      " %s(%p):%p ref [%s] %s(%p):%p\n",
    130                     referrer->descriptor, referrer->classLoader,
    131                     referrer->pDvmDex,
    132                     resClass->descriptor, resClassCheck->descriptor,
    133                     resClassCheck->classLoader, resClassCheck->pDvmDex);
    134                 LOGW("(%s had used a different %s during pre-verification)\n",
    135                     referrer->descriptor, resClass->descriptor);
    136                 dvmThrowException("Ljava/lang/IllegalAccessError;",
    137                     "Class ref in pre-verified class resolved to unexpected "
    138                     "implementation");
    139                 return NULL;
    140             }
    141         }
    142 
    143         LOGVV("##### +ResolveClass(%s): referrer=%s dex=%p ldr=%p ref=%d\n",
    144             resClass->descriptor, referrer->descriptor, referrer->pDvmDex,
    145             referrer->classLoader, classIdx);
    146 
    147         /*
    148          * Add what we found to the list so we can skip the class search
    149          * next time through.
    150          *
    151          * TODO: should we be doing this when fromUnverifiedConstant==true?
    152          * (see comments at top of oo/Class.c)
    153          */
    154         dvmDexSetResolvedClass(pDvmDex, classIdx, resClass);
    155     } else {
    156         /* not found, exception should be raised */
    157         LOGVV("Class not found: %s\n",
    158             dexStringByTypeIdx(pDvmDex->pDexFile, classIdx));
    159         assert(dvmCheckException(dvmThreadSelf()));
    160     }
    161 
    162     return resClass;
    163 }
    164 
    165 
    166 /*
    167  * Find the method corresponding to "methodRef".
    168  *
    169  * We use "referrer" to find the DexFile with the constant pool that
    170  * "methodRef" is an index into.  We also use its class loader.  The method
    171  * being resolved may very well be in a different DEX file.
    172  *
    173  * If this is a static method, we ensure that the method's class is
    174  * initialized.
    175  */
    176 Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx,
    177     MethodType methodType)
    178 {
    179     DvmDex* pDvmDex = referrer->pDvmDex;
    180     ClassObject* resClass;
    181     const DexMethodId* pMethodId;
    182     Method* resMethod;
    183 
    184     assert(methodType != METHOD_INTERFACE);
    185 
    186     LOGVV("--- resolving method %u (referrer=%s)\n", methodIdx,
    187         referrer->descriptor);
    188     pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
    189 
    190     resClass = dvmResolveClass(referrer, pMethodId->classIdx, false);
    191     if (resClass == NULL) {
    192         /* can't find the class that the method is a part of */
    193         assert(dvmCheckException(dvmThreadSelf()));
    194         return NULL;
    195     }
    196     if (dvmIsInterfaceClass(resClass)) {
    197         /* method is part of an interface */
    198         dvmThrowExceptionWithClassMessage(
    199             "Ljava/lang/IncompatibleClassChangeError;",
    200             resClass->descriptor);
    201         return NULL;
    202     }
    203 
    204     const char* name = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
    205     DexProto proto;
    206     dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
    207 
    208     /*
    209      * We need to chase up the class hierarchy to find methods defined
    210      * in super-classes.  (We only want to check the current class
    211      * if we're looking for a constructor; since DIRECT calls are only
    212      * for constructors and private methods, we don't want to walk up.)
    213      */
    214     if (methodType == METHOD_DIRECT) {
    215         resMethod = dvmFindDirectMethod(resClass, name, &proto);
    216     } else if (methodType == METHOD_STATIC) {
    217         resMethod = dvmFindDirectMethodHier(resClass, name, &proto);
    218     } else {
    219         resMethod = dvmFindVirtualMethodHier(resClass, name, &proto);
    220     }
    221 
    222     if (resMethod == NULL) {
    223         dvmThrowException("Ljava/lang/NoSuchMethodError;", name);
    224         return NULL;
    225     }
    226 
    227     LOGVV("--- found method %d (%s.%s)\n",
    228         methodIdx, resClass->descriptor, resMethod->name);
    229 
    230     /* see if this is a pure-abstract method */
    231     if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
    232         dvmThrowException("Ljava/lang/AbstractMethodError;", name);
    233         return NULL;
    234     }
    235 
    236     /*
    237      * If we're the first to resolve this class, we need to initialize
    238      * it now.  Only necessary for METHOD_STATIC.
    239      */
    240     if (methodType == METHOD_STATIC) {
    241         if (!dvmIsClassInitialized(resMethod->clazz) &&
    242             !dvmInitClass(resMethod->clazz))
    243         {
    244             assert(dvmCheckException(dvmThreadSelf()));
    245             return NULL;
    246         } else {
    247             assert(!dvmCheckException(dvmThreadSelf()));
    248         }
    249     } else {
    250         /*
    251          * Edge case: if the <clinit> for a class creates an instance
    252          * of itself, we will call <init> on a class that is still being
    253          * initialized by us.
    254          */
    255         assert(dvmIsClassInitialized(resMethod->clazz) ||
    256                dvmIsClassInitializing(resMethod->clazz));
    257     }
    258 
    259     /*
    260      * If the class has been initialized, add a pointer to our data structure
    261      * so we don't have to jump through the hoops again.  If this is a
    262      * static method and the defining class is still initializing (i.e. this
    263      * thread is executing <clinit>), don't do the store, otherwise other
    264      * threads could call the method without waiting for class init to finish.
    265      */
    266     if (methodType == METHOD_STATIC && !dvmIsClassInitialized(resMethod->clazz))
    267     {
    268         LOGVV("--- not caching resolved method %s.%s (class init=%d/%d)\n",
    269             resMethod->clazz->descriptor, resMethod->name,
    270             dvmIsClassInitializing(resMethod->clazz),
    271             dvmIsClassInitialized(resMethod->clazz));
    272     } else {
    273         dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
    274     }
    275 
    276     return resMethod;
    277 }
    278 
    279 /*
    280  * Resolve an interface method reference.
    281  *
    282  * Returns NULL with an exception raised on failure.
    283  */
    284 Method* dvmResolveInterfaceMethod(const ClassObject* referrer, u4 methodIdx)
    285 {
    286     DvmDex* pDvmDex = referrer->pDvmDex;
    287     ClassObject* resClass;
    288     const DexMethodId* pMethodId;
    289     Method* resMethod;
    290     int i;
    291 
    292     LOGVV("--- resolving interface method %d (referrer=%s)\n",
    293         methodIdx, referrer->descriptor);
    294     pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
    295 
    296     resClass = dvmResolveClass(referrer, pMethodId->classIdx, false);
    297     if (resClass == NULL) {
    298         /* can't find the class that the method is a part of */
    299         assert(dvmCheckException(dvmThreadSelf()));
    300         return NULL;
    301     }
    302     if (!dvmIsInterfaceClass(resClass)) {
    303         /* whoops */
    304         dvmThrowExceptionWithClassMessage(
    305             "Ljava/lang/IncompatibleClassChangeError;",
    306             resClass->descriptor);
    307         return NULL;
    308     }
    309 
    310     /*
    311      * This is the first time the method has been resolved.  Set it in our
    312      * resolved-method structure.  It always resolves to the same thing,
    313      * so looking it up and storing it doesn't create a race condition.
    314      *
    315      * If we scan into the interface's superclass -- which is always
    316      * java/lang/Object -- we will catch things like:
    317      *   interface I ...
    318      *   I myobj = (something that implements I)
    319      *   myobj.hashCode()
    320      * However, the Method->methodIndex will be an offset into clazz->vtable,
    321      * rather than an offset into clazz->iftable.  The invoke-interface
    322      * code can test to see if the method returned is abstract or concrete,
    323      * and use methodIndex accordingly.  I'm not doing this yet because
    324      * (a) we waste time in an unusual case, and (b) we're probably going
    325      * to fix it in the DEX optimizer.
    326      *
    327      * We do need to scan the superinterfaces, in case we're invoking a
    328      * superinterface method on an interface reference.  The class in the
    329      * DexTypeId is for the static type of the object, not the class in
    330      * which the method is first defined.  We have the full, flattened
    331      * list in "iftable".
    332      */
    333     const char* methodName =
    334         dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
    335 
    336     DexProto proto;
    337     dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
    338 
    339     LOGVV("+++ looking for '%s' '%s' in resClass='%s'\n",
    340         methodName, methodSig, resClass->descriptor);
    341     resMethod = dvmFindVirtualMethod(resClass, methodName, &proto);
    342     if (resMethod == NULL) {
    343         LOGVV("+++ did not resolve immediately\n");
    344         for (i = 0; i < resClass->iftableCount; i++) {
    345             resMethod = dvmFindVirtualMethod(resClass->iftable[i].clazz,
    346                             methodName, &proto);
    347             if (resMethod != NULL)
    348                 break;
    349         }
    350 
    351         if (resMethod == NULL) {
    352             dvmThrowException("Ljava/lang/NoSuchMethodError;", methodName);
    353             return NULL;
    354         }
    355     } else {
    356         LOGVV("+++ resolved immediately: %s (%s %d)\n", resMethod->name,
    357             resMethod->clazz->descriptor, (u4) resMethod->methodIndex);
    358     }
    359 
    360     LOGVV("--- found interface method %d (%s.%s)\n",
    361         methodIdx, resClass->descriptor, resMethod->name);
    362 
    363     /* we're expecting this to be abstract */
    364     assert(dvmIsAbstractMethod(resMethod));
    365 
    366     /* interface methods are always public; no need to check access */
    367 
    368     /*
    369      * The interface class *may* be initialized.  According to VM spec
    370      * v2 2.17.4, the interfaces a class refers to "need not" be initialized
    371      * when the class is initialized.
    372      *
    373      * It isn't necessary for an interface class to be initialized before
    374      * we resolve methods on that interface.
    375      *
    376      * We choose not to do the initialization now.
    377      */
    378     //assert(dvmIsClassInitialized(resMethod->clazz));
    379 
    380     /*
    381      * Add a pointer to our data structure so we don't have to jump
    382      * through the hoops again.
    383      *
    384      * As noted above, no need to worry about whether the interface that
    385      * defines the method has been or is currently executing <clinit>.
    386      */
    387     dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
    388 
    389     return resMethod;
    390 }
    391 
    392 /*
    393  * Resolve an instance field reference.
    394  *
    395  * Returns NULL and throws an exception on error (no such field, illegal
    396  * access).
    397  */
    398 InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx)
    399 {
    400     DvmDex* pDvmDex = referrer->pDvmDex;
    401     ClassObject* resClass;
    402     const DexFieldId* pFieldId;
    403     InstField* resField;
    404 
    405     LOGVV("--- resolving field %u (referrer=%s cl=%p)\n",
    406         ifieldIdx, referrer->descriptor, referrer->classLoader);
    407 
    408     pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx);
    409 
    410     /*
    411      * Find the field's class.
    412      */
    413     resClass = dvmResolveClass(referrer, pFieldId->classIdx, false);
    414     if (resClass == NULL) {
    415         assert(dvmCheckException(dvmThreadSelf()));
    416         return NULL;
    417     }
    418 
    419     resField = dvmFindInstanceFieldHier(resClass,
    420         dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
    421         dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
    422     if (resField == NULL) {
    423         dvmThrowException("Ljava/lang/NoSuchFieldError;",
    424             dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
    425         return NULL;
    426     }
    427 
    428     /*
    429      * Class must be initialized by now (unless verifier is buggy).  We
    430      * could still be in the process of initializing it if the field
    431      * access is from a static initializer.
    432      */
    433     assert(dvmIsClassInitialized(resField->field.clazz) ||
    434            dvmIsClassInitializing(resField->field.clazz));
    435 
    436     /*
    437      * The class is initialized (or initializing), the field has been
    438      * found.  Add a pointer to our data structure so we don't have to
    439      * jump through the hoops again.
    440      *
    441      * Anything that uses the resolved table entry must have an instance
    442      * of the class, so any class init activity has already happened (or
    443      * been deliberately bypassed when <clinit> created an instance).
    444      * So it's always okay to update the table.
    445      */
    446     dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*)resField);
    447     LOGVV("    field %u is %s.%s\n",
    448         ifieldIdx, resField->field.clazz->descriptor, resField->field.name);
    449 
    450     return resField;
    451 }
    452 
    453 /*
    454  * Resolve a static field reference.  The DexFile format doesn't distinguish
    455  * between static and instance field references, so the "resolved" pointer
    456  * in the Dex struct will have the wrong type.  We trivially cast it here.
    457  *
    458  * Causes the field's class to be initialized.
    459  */
    460 StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx)
    461 {
    462     DvmDex* pDvmDex = referrer->pDvmDex;
    463     ClassObject* resClass;
    464     const DexFieldId* pFieldId;
    465     StaticField* resField;
    466 
    467     pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx);
    468 
    469     /*
    470      * Find the field's class.
    471      */
    472     resClass = dvmResolveClass(referrer, pFieldId->classIdx, false);
    473     if (resClass == NULL) {
    474         assert(dvmCheckException(dvmThreadSelf()));
    475         return NULL;
    476     }
    477 
    478     resField = dvmFindStaticFieldHier(resClass,
    479                 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
    480                 dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
    481     if (resField == NULL) {
    482         dvmThrowException("Ljava/lang/NoSuchFieldError;",
    483             dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
    484         return NULL;
    485     }
    486 
    487     /*
    488      * If we're the first to resolve the field in which this class resides,
    489      * we need to do it now.  Note that, if the field was inherited from
    490      * a superclass, it is not necessarily the same as "resClass".
    491      */
    492     if (!dvmIsClassInitialized(resField->field.clazz) &&
    493         !dvmInitClass(resField->field.clazz))
    494     {
    495         assert(dvmCheckException(dvmThreadSelf()));
    496         return NULL;
    497     }
    498 
    499     /*
    500      * If the class has been initialized, add a pointer to our data structure
    501      * so we don't have to jump through the hoops again.  If it's still
    502      * initializing (i.e. this thread is executing <clinit>), don't do
    503      * the store, otherwise other threads could use the field without waiting
    504      * for class init to finish.
    505      */
    506     if (dvmIsClassInitialized(resField->field.clazz)) {
    507         dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField);
    508     } else {
    509         LOGVV("--- not caching resolved field %s.%s (class init=%d/%d)\n",
    510             resField->field.clazz->descriptor, resField->field.name,
    511             dvmIsClassInitializing(resField->field.clazz),
    512             dvmIsClassInitialized(resField->field.clazz));
    513     }
    514 
    515     return resField;
    516 }
    517 
    518 
    519 /*
    520  * Resolve a string reference.
    521  *
    522  * Finding the string is easy.  We need to return a reference to a
    523  * java/lang/String object, not a bunch of characters, which means the
    524  * first time we get here we need to create an interned string.
    525  */
    526 StringObject* dvmResolveString(const ClassObject* referrer, u4 stringIdx)
    527 {
    528     DvmDex* pDvmDex = referrer->pDvmDex;
    529     StringObject* strObj;
    530     StringObject* internStrObj;
    531     const char* utf8;
    532     u4 utf16Size;
    533 
    534     LOGVV("+++ resolving string, referrer is %s\n", referrer->descriptor);
    535 
    536     /*
    537      * Create a UTF-16 version so we can trivially compare it to what's
    538      * already interned.
    539      */
    540     utf8 = dexStringAndSizeById(pDvmDex->pDexFile, stringIdx, &utf16Size);
    541     strObj = dvmCreateStringFromCstrAndLength(utf8, utf16Size);
    542     if (strObj == NULL) {
    543         /* ran out of space in GC heap? */
    544         assert(dvmCheckException(dvmThreadSelf()));
    545         goto bail;
    546     }
    547 
    548     /*
    549      * Add it to the intern list.  The return value is the one in the
    550      * intern list, which (due to race conditions) may or may not be
    551      * the one we just created.  The intern list is synchronized, so
    552      * there will be only one "live" version.
    553      *
    554      * By requesting an immortal interned string, we guarantee that
    555      * the returned object will never be collected by the GC.
    556      *
    557      * A NULL return here indicates some sort of hashing failure.
    558      */
    559     internStrObj = dvmLookupImmortalInternedString(strObj);
    560     dvmReleaseTrackedAlloc((Object*) strObj, NULL);
    561     strObj = internStrObj;
    562     if (strObj == NULL) {
    563         assert(dvmCheckException(dvmThreadSelf()));
    564         goto bail;
    565     }
    566 
    567     /* save a reference so we can go straight to the object next time */
    568     dvmDexSetResolvedString(pDvmDex, stringIdx, strObj);
    569 
    570 bail:
    571     return strObj;
    572 }
    573 
    574 /*
    575  * For debugging: return a string representing the methodType.
    576  */
    577 const char* dvmMethodTypeStr(MethodType methodType)
    578 {
    579     switch (methodType) {
    580     case METHOD_DIRECT:         return "direct";
    581     case METHOD_STATIC:         return "static";
    582     case METHOD_VIRTUAL:        return "virtual";
    583     case METHOD_INTERFACE:      return "interface";
    584     case METHOD_UNKNOWN:        return "UNKNOWN";
    585     }
    586     assert(false);
    587     return "BOGUS";
    588 }
    589