Home | History | Annotate | Download | only in native
      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  * Internal-native initialization and some common utility functions.
     19  */
     20 #include "Dalvik.h"
     21 #include "native/InternalNativePriv.h"
     22 
     23 /*
     24  * Set of classes for which we provide methods.
     25  *
     26  * The last field, classNameHash, is filled in at startup.
     27  */
     28 static DalvikNativeClass gDvmNativeMethodSet[] = {
     29     { "Ljava/lang/Object;",               dvm_java_lang_Object, 0 },
     30     { "Ljava/lang/Class;",                dvm_java_lang_Class, 0 },
     31     { "Ljava/lang/Double;",               dvm_java_lang_Double, 0 },
     32     { "Ljava/lang/Float;",                dvm_java_lang_Float, 0 },
     33     { "Ljava/lang/Math;",                 dvm_java_lang_Math, 0 },
     34     { "Ljava/lang/Runtime;",              dvm_java_lang_Runtime, 0 },
     35     { "Ljava/lang/String;",               dvm_java_lang_String, 0 },
     36     { "Ljava/lang/System;",               dvm_java_lang_System, 0 },
     37     { "Ljava/lang/Throwable;",            dvm_java_lang_Throwable, 0 },
     38     { "Ljava/lang/VMClassLoader;",        dvm_java_lang_VMClassLoader, 0 },
     39     { "Ljava/lang/VMThread;",             dvm_java_lang_VMThread, 0 },
     40     { "Ljava/lang/reflect/AccessibleObject;",
     41             dvm_java_lang_reflect_AccessibleObject, 0 },
     42     { "Ljava/lang/reflect/Array;",        dvm_java_lang_reflect_Array, 0 },
     43     { "Ljava/lang/reflect/Constructor;",
     44             dvm_java_lang_reflect_Constructor, 0 },
     45     { "Ljava/lang/reflect/Field;",        dvm_java_lang_reflect_Field, 0 },
     46     { "Ljava/lang/reflect/Method;",       dvm_java_lang_reflect_Method, 0 },
     47     { "Ljava/lang/reflect/Proxy;",        dvm_java_lang_reflect_Proxy, 0 },
     48     { "Ljava/util/concurrent/atomic/AtomicLong;",
     49             dvm_java_util_concurrent_atomic_AtomicLong, 0 },
     50     { "Ldalvik/bytecode/OpcodeInfo;",     dvm_dalvik_bytecode_OpcodeInfo, 0 },
     51     { "Ldalvik/system/VMDebug;",          dvm_dalvik_system_VMDebug, 0 },
     52     { "Ldalvik/system/DexFile;",          dvm_dalvik_system_DexFile, 0 },
     53     { "Ldalvik/system/VMRuntime;",        dvm_dalvik_system_VMRuntime, 0 },
     54     { "Ldalvik/system/Zygote;",           dvm_dalvik_system_Zygote, 0 },
     55     { "Ldalvik/system/VMStack;",          dvm_dalvik_system_VMStack, 0 },
     56     { "Lorg/apache/harmony/dalvik/ddmc/DdmServer;",
     57             dvm_org_apache_harmony_dalvik_ddmc_DdmServer, 0 },
     58     { "Lorg/apache/harmony/dalvik/ddmc/DdmVmInternal;",
     59             dvm_org_apache_harmony_dalvik_ddmc_DdmVmInternal, 0 },
     60     { "Lorg/apache/harmony/dalvik/NativeTestTarget;",
     61             dvm_org_apache_harmony_dalvik_NativeTestTarget, 0 },
     62     { "Lsun/misc/Unsafe;",                dvm_sun_misc_Unsafe, 0 },
     63     { NULL, NULL, 0 },
     64 };
     65 
     66 
     67 /*
     68  * Set up hash values on the class names.
     69  */
     70 bool dvmInternalNativeStartup()
     71 {
     72     DalvikNativeClass* classPtr = gDvmNativeMethodSet;
     73 
     74     while (classPtr->classDescriptor != NULL) {
     75         classPtr->classDescriptorHash =
     76             dvmComputeUtf8Hash(classPtr->classDescriptor);
     77         classPtr++;
     78     }
     79 
     80     gDvm.userDexFiles = dvmHashTableCreate(2, dvmFreeDexOrJar);
     81     if (gDvm.userDexFiles == NULL)
     82         return false;
     83 
     84     return true;
     85 }
     86 
     87 /*
     88  * Clean up.
     89  */
     90 void dvmInternalNativeShutdown()
     91 {
     92     dvmHashTableFree(gDvm.userDexFiles);
     93 }
     94 
     95 /*
     96  * Search the internal native set for a match.
     97  */
     98 DalvikNativeFunc dvmLookupInternalNativeMethod(const Method* method)
     99 {
    100     const char* classDescriptor = method->clazz->descriptor;
    101     const DalvikNativeClass* pClass;
    102     u4 hash;
    103 
    104     hash = dvmComputeUtf8Hash(classDescriptor);
    105     pClass = gDvmNativeMethodSet;
    106     while (true) {
    107         if (pClass->classDescriptor == NULL)
    108             break;
    109         if (pClass->classDescriptorHash == hash &&
    110             strcmp(pClass->classDescriptor, classDescriptor) == 0)
    111         {
    112             const DalvikNativeMethod* pMeth = pClass->methodInfo;
    113             while (true) {
    114                 if (pMeth->name == NULL)
    115                     break;
    116 
    117                 if (dvmCompareNameDescriptorAndMethod(pMeth->name,
    118                     pMeth->signature, method) == 0)
    119                 {
    120                     /* match */
    121                     //LOGV("+++  match on %s.%s %s at %p",
    122                     //    className, methodName, methodSignature, pMeth->fnPtr);
    123                     return pMeth->fnPtr;
    124                 }
    125 
    126                 pMeth++;
    127             }
    128         }
    129 
    130         pClass++;
    131     }
    132 
    133     return NULL;
    134 }
    135 
    136 
    137 /*
    138  * Magic "internal native" code stub, inserted into abstract method
    139  * definitions when a class is first loaded.  This throws the expected
    140  * exception so we don't have to explicitly check for it in the interpreter.
    141  */
    142 void dvmAbstractMethodStub(const u4* args, JValue* pResult)
    143 {
    144     LOGD("--- called into dvmAbstractMethodStub");
    145     dvmThrowAbstractMethodError("abstract method not implemented");
    146 }
    147 
    148 
    149 /*
    150  * Verify that "obj" is non-null and is an instance of "clazz".
    151  * Used to implement reflection on fields and methods.
    152  *
    153  * Returns "false" and throws an exception if not.
    154  */
    155 bool dvmVerifyObjectInClass(Object* obj, ClassObject* clazz) {
    156     ClassObject* exceptionClass = NULL;
    157     if (obj == NULL) {
    158         exceptionClass = gDvm.exNullPointerException;
    159     } else if (!dvmInstanceof(obj->clazz, clazz)) {
    160         exceptionClass = gDvm.exIllegalArgumentException;
    161     }
    162 
    163     if (exceptionClass == NULL) {
    164         return true;
    165     }
    166 
    167     std::string expectedClassName(dvmHumanReadableDescriptor(clazz->descriptor));
    168     std::string actualClassName(dvmHumanReadableType(obj));
    169     dvmThrowExceptionFmt(exceptionClass, "expected receiver of type %s, but got %s",
    170             expectedClassName.c_str(), actualClassName.c_str());
    171     return false;
    172 }
    173 
    174 /*
    175  * Find a class by name, initializing it if requested.
    176  */
    177 ClassObject* dvmFindClassByName(StringObject* nameObj, Object* loader,
    178     bool doInit)
    179 {
    180     ClassObject* clazz = NULL;
    181     char* name = NULL;
    182     char* descriptor = NULL;
    183 
    184     if (nameObj == NULL) {
    185         dvmThrowNullPointerException("name == null");
    186         goto bail;
    187     }
    188     name = dvmCreateCstrFromString(nameObj);
    189 
    190     /*
    191      * We need to validate and convert the name (from x.y.z to x/y/z).  This
    192      * is especially handy for array types, since we want to avoid
    193      * auto-generating bogus array classes.
    194      */
    195     if (!dexIsValidClassName(name, true)) {
    196         LOGW("dvmFindClassByName rejecting '%s'", name);
    197         dvmThrowClassNotFoundException(name);
    198         goto bail;
    199     }
    200 
    201     descriptor = dvmDotToDescriptor(name);
    202     if (descriptor == NULL) {
    203         goto bail;
    204     }
    205 
    206     if (doInit)
    207         clazz = dvmFindClass(descriptor, loader);
    208     else
    209         clazz = dvmFindClassNoInit(descriptor, loader);
    210 
    211     if (clazz == NULL) {
    212         LOGVV("FAIL: load %s (%d)", descriptor, doInit);
    213         Thread* self = dvmThreadSelf();
    214         Object* oldExcep = dvmGetException(self);
    215         dvmAddTrackedAlloc(oldExcep, self);     /* don't let this be GCed */
    216         dvmClearException(self);
    217         dvmThrowChainedClassNotFoundException(name, oldExcep);
    218         dvmReleaseTrackedAlloc(oldExcep, self);
    219     } else {
    220         LOGVV("GOOD: load %s (%d) --> %p ldr=%p",
    221             descriptor, doInit, clazz, clazz->classLoader);
    222     }
    223 
    224 bail:
    225     free(name);
    226     free(descriptor);
    227     return clazz;
    228 }
    229 
    230 /*
    231  * We insert native method stubs for abstract methods so we don't have to
    232  * check the access flags at the time of the method call.  This results in
    233  * "native abstract" methods, which can't exist.  If we see the "abstract"
    234  * flag set, clear the "native" flag.
    235  *
    236  * We also move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
    237  * position, because the callers of this function are trying to convey
    238  * the "traditional" meaning of the flags to their callers.
    239  */
    240 u4 dvmFixMethodFlags(u4 flags)
    241 {
    242     if ((flags & ACC_ABSTRACT) != 0) {
    243         flags &= ~ACC_NATIVE;
    244     }
    245 
    246     flags &= ~ACC_SYNCHRONIZED;
    247 
    248     if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) {
    249         flags |= ACC_SYNCHRONIZED;
    250     }
    251 
    252     return flags & JAVA_FLAGS_MASK;
    253 }
    254