dalvikvm.cc revision fa42b4410d49134a8e63dc2196be4013d286f2d6
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 2fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom * copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 166b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro 17fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom#include <dlfcn.h> 182ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro#include <signal.h> 1990a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes 2090a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include <cstdio> 2190a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include <cstring> 222ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro#include <string> 237b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro 242ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro#include "jni.h" 25eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "ScopedLocalRef.h" 26eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "toStringArray.h" 27eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "UniquePtr.h" 282ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 2911d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art { 3011d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes 312ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro// Determine whether or not the specified method is public. 32e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughesstatic bool IsMethodPublic(JNIEnv* env, jclass c, jmethodID method_id) { 33e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes ScopedLocalRef<jobject> reflected(env, env->ToReflectedMethod(c, method_id, JNI_FALSE)); 342ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (reflected.get() == NULL) { 353320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom fprintf(stderr, "Failed to get reflected method\n"); 362ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro return false; 372ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 382ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // We now have a Method instance. We need to call its 392ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // getModifiers() method. 40fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom jclass method_class = env->FindClass("java/lang/reflect/Method"); 41fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom if (method_class == NULL) { 42fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom fprintf(stderr, "Failed to find class java.lang.reflect.Method\n"); 43fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom return false; 44fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom } 45fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom jmethodID mid = env->GetMethodID(method_class, "getModifiers", "()I"); 46eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes if (mid == NULL) { 47eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes fprintf(stderr, "Failed to find java.lang.reflect.Method.getModifiers\n"); 482ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro return false; 492ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 50eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes int modifiers = env->CallIntMethod(reflected.get(), mid); 51fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom static const int PUBLIC = 0x0001; // java.lang.reflect.Modifiers.PUBLIC 52fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom if ((modifiers & PUBLIC) == 0) { 532ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro return false; 542ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 552ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro return true; 562ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro} 572ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 581bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesstatic int InvokeMain(JNIEnv* env, char** argv) { 592ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // We want to call main() with a String array with our arguments in 602ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // it. Create an array and populate it. Note argv[0] is not 612ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // included. 620a96fe07175b960050a606fadbf76d85a060e4faElliott Hughes ScopedLocalRef<jobjectArray> args(env, toStringArray(env, argv + 1)); 632ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (args.get() == NULL) { 64d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes env->ExceptionDescribe(); 65d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes return EXIT_FAILURE; 662ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 672ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 682ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // Find [class].main(String[]). 692ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 702ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // Convert "com.android.Blah" to "com/android/Blah". 71e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes std::string class_name(argv[0]); 722ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro std::replace(class_name.begin(), class_name.end(), '.', '/'); 732ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 740dab4ecc01c5db0d0846bf5b4f608634d7404f74Elliott Hughes ScopedLocalRef<jclass> klass(env, env->FindClass(class_name.c_str())); 752ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (klass.get() == NULL) { 762ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro fprintf(stderr, "Unable to locate class '%s'\n", class_name.c_str()); 77d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes env->ExceptionDescribe(); 78d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes return EXIT_FAILURE; 792ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 802ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 81d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes jmethodID method = env->GetStaticMethodID(klass.get(), "main", "([Ljava/lang/String;)V"); 822ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (method == NULL) { 83d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes fprintf(stderr, "Unable to find static main(String[]) in '%s'\n", class_name.c_str()); 84d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes env->ExceptionDescribe(); 85d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes return EXIT_FAILURE; 862ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 872ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 882ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // Make sure the method is public. JNI doesn't prevent us from 892ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // calling a private method, so we have to check it explicitly. 902ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (!IsMethodPublic(env, klass.get(), method)) { 91d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes fprintf(stderr, "Sorry, main() is not public in '%s'\n", class_name.c_str()); 92d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes env->ExceptionDescribe(); 93d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes return EXIT_FAILURE; 942ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 952ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 962ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // Invoke main(). 972ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro env->CallStaticVoidMethod(klass.get(), method, args.get()); 980c8c6732ee872d6f475db6cd6c8e205e152b113cElliott Hughes 990c8c6732ee872d6f475db6cd6c8e205e152b113cElliott Hughes // Check whether there was an uncaught exception. We don't log any uncaught exception here; 1000c8c6732ee872d6f475db6cd6c8e205e152b113cElliott Hughes // detaching this thread will do that for us, but it will clear the exception (and invalidate 1010c8c6732ee872d6f475db6cd6c8e205e152b113cElliott Hughes // our JNIEnv), so we need to check here. 1020c8c6732ee872d6f475db6cd6c8e205e152b113cElliott Hughes return env->ExceptionCheck() ? EXIT_FAILURE : EXIT_SUCCESS; 1032ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro} 1042ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 10581ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes// Parse arguments. Most of it just gets passed through to the runtime. 1062ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro// The JNI spec defines a handful of standard arguments. 107fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstromstatic int dalvikvm(int argc, char** argv) { 1082ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro setvbuf(stdout, NULL, _IONBF, 0); 1092ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 1102ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // Skip over argv[0]. 1112ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro argv++; 1122ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro argc--; 1132ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 1142ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // If we're adding any additional stuff, e.g. function hook specifiers, 1152ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // add them to the count here. 1162ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // 11781ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // We're over-allocating, because this includes the options to the runtime 1182ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // plus the options to the program. 1192ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro int option_count = argc; 12090a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes UniquePtr<JavaVMOption[]> options(new JavaVMOption[option_count]()); 1212ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 1222ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // Copy options over. Everything up to the name of the class starts 1232ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // with a '-' (the function hook stuff is strictly internal). 1242ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // 1252ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // [Do we need to catch & handle "-jar" here?] 1262ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro bool need_extra = false; 127fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom const char* lib = "libdvm.so"; 128fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom const char* debug = NULL; 12981ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes const char* what = NULL; 1302ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro int curr_opt, arg_idx; 1312ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro for (curr_opt = arg_idx = 0; arg_idx < argc; arg_idx++) { 1322ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (argv[arg_idx][0] != '-' && !need_extra) { 1332ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro break; 1342ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 135fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom if (strncmp(argv[arg_idx], "-XXlib:", strlen("-XXlib:")) == 0) { 136fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom lib = argv[arg_idx] + strlen("-XXlib:"); 137fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom continue; 138fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom } 139fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom 1402ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro options[curr_opt++].optionString = argv[arg_idx]; 1412ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 1422ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // Some options require an additional argument. 1432ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro need_extra = false; 144d6fe38d96b6116bd53cf2cb14734af8d69e08661Elliott Hughes if (strcmp(argv[arg_idx], "-classpath") == 0 || strcmp(argv[arg_idx], "-cp") == 0) { 1452ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro need_extra = true; 14681ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes what = argv[arg_idx]; 1472ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 1482ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 1492ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 1502ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (need_extra) { 15181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes fprintf(stderr, "%s must be followed by an additional argument giving a value\n", what); 1522ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro return EXIT_FAILURE; 1532ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 1542ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 15581ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // Make sure they provided a class name. 1562ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (arg_idx == argc) { 1572ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro fprintf(stderr, "Class name required\n"); 1582ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro return EXIT_FAILURE; 1592ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 1602ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 1612ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro // insert additional internal options here 1622ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 163fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom if (curr_opt >= option_count) { 164fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom fprintf(stderr, "curr_opt(%d) >= option_count(%d)\n", curr_opt, option_count); 165fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom abort(); 166fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom return EXIT_FAILURE; 167fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom } 168fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom 169fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom // Find the JNI_CreateJavaVM implementation. 170fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom std::string library(lib); 171fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom if (debug != NULL) { 172fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom library += debug; 173fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom } 174fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom void* handle = dlopen(library.c_str(), RTLD_NOW); 175fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom if (handle == NULL) { 176fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom fprintf(stderr, "Failed to dlopen library %s: %s\n", library.c_str(), dlerror()); 177fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom return EXIT_FAILURE; 178fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom } 179fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom const char* symbol = "JNI_CreateJavaVM"; 180fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom void* sym = dlsym(handle, symbol); 181fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom if (handle == NULL) { 182fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom fprintf(stderr, "Failed to find symbol %s: %s\n", symbol, dlerror()); 183fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom return EXIT_FAILURE; 184fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom } 185fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom typedef int (*Fn)(JavaVM** p_vm, JNIEnv** p_env, void* vm_args); 186fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom Fn JNI_CreateJavaVM = reinterpret_cast<Fn>(sym); 1872ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 1882ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro JavaVMInitArgs init_args; 189f2682d5a6ce0f7de58da8fd4ec8aec200c43b92eElliott Hughes init_args.version = JNI_VERSION_1_6; 1902ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro init_args.options = options.get(); 1912ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro init_args.nOptions = curr_opt; 1922ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro init_args.ignoreUnrecognized = JNI_FALSE; 1932ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 19481ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // Start the runtime. The current thread becomes the main thread. 1952ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro JavaVM* vm = NULL; 1962ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro JNIEnv* env = NULL; 1972ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro if (JNI_CreateJavaVM(&vm, &env, &init_args) != JNI_OK) { 198fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom fprintf(stderr, "Failed to initialize runtime (check log for details)\n"); 1992ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro return EXIT_FAILURE; 2002ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 2012ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 2021bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes int rc = InvokeMain(env, &argv[arg_idx]); 2032ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 20417057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes#if defined(NDEBUG) 20517057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes // The DestroyJavaVM call will detach this thread for us. In debug builds, we don't want to 20617057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes // detach because detaching disables the CheckSafeToLockOrUnlock checking. 207f2682d5a6ce0f7de58da8fd4ec8aec200c43b92eElliott Hughes if (vm->DetachCurrentThread() != JNI_OK) { 2082ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro fprintf(stderr, "Warning: unable to detach main thread\n"); 209c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes rc = EXIT_FAILURE; 2102ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 21117057b15cb8d8da97b2bc28fd38bdcc7a34e846eElliott Hughes#endif 2122ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 213f2682d5a6ce0f7de58da8fd4ec8aec200c43b92eElliott Hughes if (vm->DestroyJavaVM() != 0) { 21481ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes fprintf(stderr, "Warning: runtime did not shut down cleanly\n"); 215c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes rc = EXIT_FAILURE; 2162ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro } 2172ed144c2b49ae1da6c464d7a1be0062870530802Carl Shapiro 218c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes return rc; 2197b21670581d13db32f1384a3b2692bcfc8f57320Carl Shapiro} 22011d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes 22111d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes} // namespace art 22211d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes 22311d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesint main(int argc, char** argv) { 224fa42b4410d49134a8e63dc2196be4013d286f2d6Brian Carlstrom return art::dalvikvm(argc, argv); 22511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes} 226