修改拨动开关
[mytuuics.git] / dalvik / dalvikvm / Main.cpp
blob4aa6e207b34e3eb001f2eb7029b9d30ed4a5cd93
1 /*
2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * Command-line invocation of the Dalvik VM.
19 #include "jni.h"
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <signal.h>
25 #include <assert.h>
29 * We want failed write() calls to just return with an error.
31 static void blockSigpipe()
33 sigset_t mask;
35 sigemptyset(&mask);
36 sigaddset(&mask, SIGPIPE);
37 if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
38 fprintf(stderr, "WARNING: SIGPIPE not blocked\n");
42 * Create a String[] and populate it with the contents of argv.
44 static jobjectArray createStringArray(JNIEnv* env, char* const argv[], int argc)
46 jclass stringClass = NULL;
47 jobjectArray strArray = NULL;
48 jobjectArray result = NULL;
49 int i;
51 stringClass = env->FindClass("java/lang/String");
52 if (env->ExceptionCheck()) {
53 fprintf(stderr, "Got exception while finding class String\n");
54 goto bail;
56 assert(stringClass != NULL);
57 strArray = env->NewObjectArray(argc, stringClass, NULL);
58 if (env->ExceptionCheck()) {
59 fprintf(stderr, "Got exception while creating String array\n");
60 goto bail;
62 assert(strArray != NULL);
64 for (i = 0; i < argc; i++) {
65 jstring argStr;
67 argStr = env->NewStringUTF(argv[i]);
68 if (env->ExceptionCheck()) {
69 fprintf(stderr, "Got exception while allocating Strings\n");
70 goto bail;
72 assert(argStr != NULL);
73 env->SetObjectArrayElement(strArray, i, argStr);
74 env->DeleteLocalRef(argStr);
77 /* return the array, and ensure we don't delete the local ref to it */
78 result = strArray;
79 strArray = NULL;
81 bail:
82 env->DeleteLocalRef(stringClass);
83 env->DeleteLocalRef(strArray);
84 return result;
88 * Determine whether or not the specified method is public.
90 * Returns JNI_TRUE on success, JNI_FALSE on failure.
92 static int methodIsPublic(JNIEnv* env, jclass clazz, jmethodID methodId)
94 static const int PUBLIC = 0x0001; // java.lang.reflect.Modifiers.PUBLIC
95 jobject refMethod = NULL;
96 jclass methodClass = NULL;
97 jmethodID getModifiersId;
98 int modifiers;
99 int result = JNI_FALSE;
101 refMethod = env->ToReflectedMethod(clazz, methodId, JNI_FALSE);
102 if (refMethod == NULL) {
103 fprintf(stderr, "Dalvik VM unable to get reflected method\n");
104 goto bail;
108 * We now have a Method instance. We need to call
109 * its getModifiers() method.
111 methodClass = env->FindClass("java/lang/reflect/Method");
112 if (methodClass == NULL) {
113 fprintf(stderr, "Dalvik VM unable to find class Method\n");
114 goto bail;
116 getModifiersId = env->GetMethodID(methodClass,
117 "getModifiers", "()I");
118 if (getModifiersId == NULL) {
119 fprintf(stderr, "Dalvik VM unable to find reflect.Method.getModifiers\n");
120 goto bail;
123 modifiers = env->CallIntMethod(refMethod, getModifiersId);
124 if ((modifiers & PUBLIC) == 0) {
125 fprintf(stderr, "Dalvik VM: main() is not public\n");
126 goto bail;
129 result = JNI_TRUE;
131 bail:
132 env->DeleteLocalRef(refMethod);
133 env->DeleteLocalRef(methodClass);
134 return result;
138 * Parse arguments. Most of it just gets passed through to the VM. The
139 * JNI spec defines a handful of standard arguments.
141 int main(int argc, char* const argv[])
143 JavaVM* vm = NULL;
144 JNIEnv* env = NULL;
145 JavaVMInitArgs initArgs;
146 JavaVMOption* options = NULL;
147 char* slashClass = NULL;
148 int optionCount, curOpt, i, argIdx;
149 int needExtra = JNI_FALSE;
150 int result = 1;
152 setvbuf(stdout, NULL, _IONBF, 0);
154 /* ignore argv[0] */
155 argv++;
156 argc--;
159 * If we're adding any additional stuff, e.g. function hook specifiers,
160 * add them to the count here.
162 * We're over-allocating, because this includes the options to the VM
163 * plus the options to the program.
165 optionCount = argc;
167 options = (JavaVMOption*) malloc(sizeof(JavaVMOption) * optionCount);
168 memset(options, 0, sizeof(JavaVMOption) * optionCount);
171 * Copy options over. Everything up to the name of the class starts
172 * with a '-' (the function hook stuff is strictly internal).
174 * [Do we need to catch & handle "-jar" here?]
176 for (curOpt = argIdx = 0; argIdx < argc; argIdx++) {
177 if (argv[argIdx][0] != '-' && !needExtra)
178 break;
179 options[curOpt++].optionString = strdup(argv[argIdx]);
181 /* some options require an additional arg */
182 needExtra = JNI_FALSE;
183 if (strcmp(argv[argIdx], "-classpath") == 0 ||
184 strcmp(argv[argIdx], "-cp") == 0)
185 /* others? */
187 needExtra = JNI_TRUE;
191 if (needExtra) {
192 fprintf(stderr, "Dalvik VM requires value after last option flag\n");
193 goto bail;
196 /* insert additional internal options here */
198 assert(curOpt <= optionCount);
200 initArgs.version = JNI_VERSION_1_4;
201 initArgs.options = options;
202 initArgs.nOptions = curOpt;
203 initArgs.ignoreUnrecognized = JNI_FALSE;
205 //printf("nOptions = %d\n", initArgs.nOptions);
207 blockSigpipe();
210 * Start VM. The current thread becomes the main thread of the VM.
212 if (JNI_CreateJavaVM(&vm, &env, &initArgs) < 0) {
213 fprintf(stderr, "Dalvik VM init failed (check log file)\n");
214 goto bail;
218 * Make sure they provided a class name. We do this after VM init
219 * so that things like "-Xrunjdwp:help" have the opportunity to emit
220 * a usage statement.
222 if (argIdx == argc) {
223 fprintf(stderr, "Dalvik VM requires a class name\n");
224 goto bail;
228 * We want to call main() with a String array with our arguments in it.
229 * Create an array and populate it. Note argv[0] is not included.
231 jobjectArray strArray;
232 strArray = createStringArray(env, &argv[argIdx+1], argc-argIdx-1);
233 if (strArray == NULL)
234 goto bail;
237 * Find [class].main(String[]).
239 jclass startClass;
240 jmethodID startMeth;
241 char* cp;
243 /* convert "com.android.Blah" to "com/android/Blah" */
244 slashClass = strdup(argv[argIdx]);
245 for (cp = slashClass; *cp != '\0'; cp++)
246 if (*cp == '.')
247 *cp = '/';
249 startClass = env->FindClass(slashClass);
250 if (startClass == NULL) {
251 fprintf(stderr, "Dalvik VM unable to locate class '%s'\n", slashClass);
252 goto bail;
255 startMeth = env->GetStaticMethodID(startClass,
256 "main", "([Ljava/lang/String;)V");
257 if (startMeth == NULL) {
258 fprintf(stderr, "Dalvik VM unable to find static main(String[]) in '%s'\n",
259 slashClass);
260 goto bail;
264 * Make sure the method is public. JNI doesn't prevent us from calling
265 * a private method, so we have to check it explicitly.
267 if (!methodIsPublic(env, startClass, startMeth))
268 goto bail;
271 * Invoke main().
273 env->CallStaticVoidMethod(startClass, startMeth, strArray);
275 if (!env->ExceptionCheck())
276 result = 0;
278 bail:
279 /*printf("Shutting down Dalvik VM\n");*/
280 if (vm != NULL) {
282 * This allows join() and isAlive() on the main thread to work
283 * correctly, and also provides uncaught exception handling.
285 if (vm->DetachCurrentThread() != JNI_OK) {
286 fprintf(stderr, "Warning: unable to detach main thread\n");
287 result = 1;
290 if (vm->DestroyJavaVM() != 0)
291 fprintf(stderr, "Warning: Dalvik VM did not shut down cleanly\n");
292 /*printf("\nDalvik VM has exited\n");*/
295 for (i = 0; i < optionCount; i++)
296 free((char*) options[i].optionString);
297 free(options);
298 free(slashClass);
299 /*printf("--- VM is down, process exiting\n");*/
300 return result;