// This complements the treatment of NATIVELOADER_DEFAULT_NAMESPACE_LIBS in // art/libnativeloader/native_loader.cpp: The libraries listed in that variable // are added to the default namespace, which for dalvikvm runs means they can // access all internal libs in com_android_art. However, to allow the opposite // direction we need links for them from com_android_art back to default, and // that's done here. See comments in native_loader.cpp for full discussion. staticbool initNativeloaderExtraLibsLinks() { #ifdef ART_TARGET_ANDROID constchar* links = getenv("NATIVELOADER_DEFAULT_NAMESPACE_LIBS"); if (links == nullptr || *links == 0) { returntrue;
} struct android_namespace_t* art_ns = android_get_exported_namespace("com_android_art"); if (art_ns == nullptr) {
fprintf(stderr, "Warning: com_android_art namespace not found - " "NATIVELOADER_DEFAULT_NAMESPACE_LIBS ignored\n"); returntrue;
} if (!android_link_namespaces(art_ns, nullptr, links)) {
fprintf(stderr, "Error adding linker namespace links from com_android_art to default for %s: %s",
links,
dlerror()); returnfalse;
} #endif// ART_TARGET_ANDROID returntrue;
}
// Determine whether or not the specified method is public. staticbool IsMethodPublic(JNIEnv* env, jclass c, jmethodID method_id) {
ScopedLocalRef<jobject> reflected(env, env->ToReflectedMethod(c, method_id, JNI_FALSE)); if (reflected.get() == nullptr) {
fprintf(stderr, "Failed to get reflected method\n"); returnfalse;
} // We now have a Method instance. We need to call its // getModifiers() method.
jclass method_class = env->FindClass("java/lang/reflect/Method"); if (method_class == nullptr) {
fprintf(stderr, "Failed to find class java.lang.reflect.Method\n"); returnfalse;
}
jmethodID mid = env->GetMethodID(method_class, "getModifiers", "()I"); if (mid == nullptr) {
fprintf(stderr, "Failed to find java.lang.reflect.Method.getModifiers\n"); returnfalse;
} int modifiers = env->CallIntMethod(reflected.get(), mid); staticconstintPUBLIC = 0x0001; // java.lang.reflect.Modifiers.PUBLIC if ((modifiers & PUBLIC) == 0) {
fprintf(stderr, "Modifiers mismatch\n"); returnfalse;
} returntrue;
}
staticint InvokeMain(JNIEnv* env, char** argv) { // We want to call main() with a String array with our arguments in // it. Create an array and populate it. Note argv[0] is not // included.
ScopedLocalRef<jobjectArray> args(env, toStringArray(env, argv + 1)); if (args.get() == nullptr) {
env->ExceptionDescribe(); return EXIT_FAILURE;
}
ScopedLocalRef<jclass> klass(env, env->FindClass(class_name.c_str())); if (klass.get() == nullptr) {
fprintf(stderr, "Unable to locate class '%s'\n", class_name.c_str());
env->ExceptionDescribe(); return EXIT_FAILURE;
}
jmethodID method = env->GetStaticMethodID(klass.get(), "main", "([Ljava/lang/String;)V"); if (method == nullptr) {
fprintf(stderr, "Unable to find static main(String[]) in '%s'\n", class_name.c_str());
env->ExceptionDescribe(); return EXIT_FAILURE;
}
// Make sure the method is public. JNI doesn't prevent us from // calling a private method, so we have to check it explicitly. if (!IsMethodPublic(env, klass.get(), method)) {
fprintf(stderr, "Sorry, main() is not public in '%s'\n", class_name.c_str());
env->ExceptionDescribe(); return EXIT_FAILURE;
}
// Check whether there was an uncaught exception. We don't log any uncaught exception here; // detaching this thread will do that for us, but it will clear the exception (and invalidate // our JNIEnv), so we need to check here. return env->ExceptionCheck() ? EXIT_FAILURE : EXIT_SUCCESS;
}
// Parse arguments. Most of it just gets passed through to the runtime. // The JNI spec defines a handful of standard arguments. staticint dalvikvm(int argc, char** argv) {
setvbuf(stdout, nullptr, _IONBF, 0);
// Skip over argv[0].
argv++;
argc--;
// If we're adding any additional stuff, e.g. function hook specifiers, // add them to the count here. // // We're over-allocating, because this includes the options to the runtime // plus the options to the program. int option_count = argc;
std::unique_ptr<JavaVMOption[]> options(new JavaVMOption[option_count]());
// Copy options over. Everything up to the name of the class starts // with a '-' (the function hook stuff is strictly internal). // // [Do we need to catch & handle "-jar" here?] bool need_extra = false; constchar* lib = nullptr; constchar* what = nullptr; int curr_opt, arg_idx; for (curr_opt = arg_idx = 0; arg_idx < argc; arg_idx++) { if (argv[arg_idx][0] != '-' && !need_extra) { break;
} if (strncmp(argv[arg_idx], "-XXlib:", strlen("-XXlib:")) == 0) {
lib = argv[arg_idx] + strlen("-XXlib:"); continue;
}
options[curr_opt++].optionString = argv[arg_idx];
// Some options require an additional argument.
need_extra = false; if (strcmp(argv[arg_idx], "-classpath") == 0 || strcmp(argv[arg_idx], "-cp") == 0) {
need_extra = true;
what = argv[arg_idx];
}
}
if (!initNativeloaderExtraLibsLinks()) { return EXIT_FAILURE;
}
if (need_extra) {
fprintf(stderr, "%s must be followed by an additional argument giving a value\n", what); return EXIT_FAILURE;
}
// Find the JNI_CreateJavaVM implementation.
JniInvocation jni_invocation; if (!jni_invocation.Init(lib)) {
fprintf(stderr, "Failed to initialize JNI invocation API from %s\n", lib); return EXIT_FAILURE;
}
// Start the runtime. The current thread becomes the main thread.
JavaVM* vm = nullptr;
JNIEnv* env = nullptr; if (JNI_CreateJavaVM(&vm, &env, &init_args) != JNI_OK) {
fprintf(stderr, "Failed to initialize runtime (check log for details)\n"); return EXIT_FAILURE;
}
// Make sure they provided a class name. We do this after // JNI_CreateJavaVM so that things like "-help" have the opportunity // to emit a usage statement. if (arg_idx == argc) {
fprintf(stderr, "Class name required\n"); return EXIT_FAILURE;
}
int rc = InvokeMain(env, &argv[arg_idx]);
#ifdefined(NDEBUG) // The DestroyJavaVM call will detach this thread for us. In debug builds, we don't want to // detach because detaching disables the CheckSafeToLockOrUnlock checking. if (vm->DetachCurrentThread() != JNI_OK) {
fprintf(stderr, "Warning: unable to detach main thread\n");
rc = EXIT_FAILURE;
} #endif
if (vm->DestroyJavaVM() != 0) {
fprintf(stderr, "Warning: runtime did not shut down cleanly\n");
rc = EXIT_FAILURE;
}
int main(int argc, char** argv) { // Do not allow static destructors to be called, since it's conceivable that // daemons may still awaken (literally).
art::FastExit(art::dalvikvm(argc, argv));
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.