runtime.cc revision f1a5adc87760f938b01df26d906295063546b259
1/* 2 * Copyright (C) 2011 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#include "runtime.h" 18 19#include <signal.h> 20 21#include <cstdio> 22#include <cstdlib> 23#include <limits> 24#include <vector> 25 26#include "class_linker.h" 27#include "class_loader.h" 28#include "debugger.h" 29#include "dex_verifier.h" 30#include "heap.h" 31#include "image.h" 32#include "intern_table.h" 33#include "jni_internal.h" 34#include "monitor.h" 35#include "oat_file.h" 36#include "ScopedLocalRef.h" 37#include "signal_catcher.h" 38#include "space.h" 39#include "thread.h" 40#include "thread_list.h" 41#include "UniquePtr.h" 42 43// TODO: this drags in cutil/log.h, which conflicts with our logging.h. 44#include "JniConstants.h" 45 46namespace art { 47 48Runtime* Runtime::instance_ = NULL; 49 50Mutex Runtime::abort_lock_("abort lock"); 51 52Runtime::Runtime() 53 : is_compiler_(false), 54 is_zygote_(false), 55 default_stack_size_(Thread::kDefaultStackSize), 56 monitor_list_(NULL), 57 thread_list_(NULL), 58 intern_table_(NULL), 59 class_linker_(NULL), 60 signal_catcher_(NULL), 61 java_vm_(NULL), 62 jni_stub_array_(NULL), 63 abstract_method_error_stub_array_(NULL), 64 shutting_down_(false), 65 started_(false), 66 vfprintf_(NULL), 67 exit_(NULL), 68 abort_(NULL), 69 stats_enabled_(false), 70 tracer_(NULL) { 71 for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) { 72 resolution_stub_array_[i] = NULL; 73 } 74 for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 75 callee_save_method_[i] = NULL; 76 } 77} 78 79Runtime::~Runtime() { 80 shutting_down_ = true; 81 82 Dbg::StopJdwp(); 83 84 // Make sure our internal threads are dead before we start tearing down things they're using. 85 delete signal_catcher_; 86 // TODO: GC thread. 87 88 // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended. 89 delete thread_list_; 90 delete monitor_list_; 91 92 delete class_linker_; 93 Heap::Destroy(); 94 verifier::DexVerifier::DeleteGcMaps(); 95 delete intern_table_; 96 delete java_vm_; 97 Thread::Shutdown(); 98 // TODO: acquire a static mutex on Runtime to avoid racing. 99 CHECK(instance_ == NULL || instance_ == this); 100 instance_ = NULL; 101} 102 103static bool gAborting = false; 104 105struct AbortState { 106 void Dump(std::ostream& os) { 107 if (gAborting) { 108 os << "Runtime aborting --- recursively, so no thread-specific detail!\n"; 109 return; 110 } 111 gAborting = true; 112 os << "Runtime aborting...\n"; 113 if (Runtime::Current() == NULL) { 114 os << "(Runtime does not yet exist!)\n"; 115 return; 116 } 117 Thread* self = Thread::Current(); 118 if (self == NULL) { 119 os << "(Aborting thread was not attached to runtime!)\n"; 120 } else { 121 self->Dump(os); 122 if (self->IsExceptionPending()) { 123 os << "Pending " << PrettyTypeOf(self->GetException()) << " on thread:\n" 124 << self->GetException()->Dump(); 125 } 126 } 127 } 128}; 129 130void Runtime::Abort(const char* file, int line) { 131 // Ensure that we don't have multiple threads trying to abort at once, 132 // which would result in significantly worse diagnostics. 133 MutexLock mu(abort_lock_); 134 135 // Get any pending output out of the way. 136 fflush(NULL); 137 138 // Many people have difficulty distinguish aborts from crashes, 139 // so be explicit. 140 AbortState state; 141 LOG(INTERNAL_FATAL) << Dumpable<AbortState>(state); 142 143 // Perform any platform-specific pre-abort actions. 144 PlatformAbort(file, line); 145 146 // use abort hook if we have one 147 if (Runtime::Current() != NULL && Runtime::Current()->abort_ != NULL) { 148 Runtime::Current()->abort_(); 149 // notreached 150 } 151 152 // If we call abort(3) on a device, all threads in the process 153 // receive SIGABRT. debuggerd dumps the stack trace of the main 154 // thread, whether or not that was the thread that failed. By 155 // stuffing a value into a bogus address, we cause a segmentation 156 // fault in the current thread, and get a useful log from debuggerd. 157 // We can also trivially tell the difference between a VM crash and 158 // a deliberate abort by looking at the fault address. 159 *reinterpret_cast<char*>(0xdeadd00d) = 38; 160 abort(); 161 // notreached 162} 163 164void Runtime::CallExitHook(jint status) { 165 if (exit_ != NULL) { 166 ScopedThreadStateChange tsc(Thread::Current(), Thread::kNative); 167 exit_(status); 168 LOG(WARNING) << "Exit hook returned instead of exiting!"; 169 } 170} 171 172// Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify 173// memory sizes. [kK] indicates kilobytes, [mM] megabytes, and 174// [gG] gigabytes. 175// 176// "s" should point just past the "-Xm?" part of the string. 177// "div" specifies a divisor, e.g. 1024 if the value must be a multiple 178// of 1024. 179// 180// The spec says the -Xmx and -Xms options must be multiples of 1024. It 181// doesn't say anything about -Xss. 182// 183// Returns 0 (a useless size) if "s" is malformed or specifies a low or 184// non-evenly-divisible value. 185// 186size_t ParseMemoryOption(const char* s, size_t div) { 187 // strtoul accepts a leading [+-], which we don't want, 188 // so make sure our string starts with a decimal digit. 189 if (isdigit(*s)) { 190 const char* s2; 191 size_t val = strtoul(s, (char**)&s2, 10); 192 if (s2 != s) { 193 // s2 should be pointing just after the number. 194 // If this is the end of the string, the user 195 // has specified a number of bytes. Otherwise, 196 // there should be exactly one more character 197 // that specifies a multiplier. 198 if (*s2 != '\0') { 199 // The remainder of the string is either a single multiplier 200 // character, or nothing to indicate that the value is in 201 // bytes. 202 char c = *s2++; 203 if (*s2 == '\0') { 204 size_t mul; 205 if (c == '\0') { 206 mul = 1; 207 } else if (c == 'k' || c == 'K') { 208 mul = KB; 209 } else if (c == 'm' || c == 'M') { 210 mul = MB; 211 } else if (c == 'g' || c == 'G') { 212 mul = GB; 213 } else { 214 // Unknown multiplier character. 215 return 0; 216 } 217 218 if (val <= std::numeric_limits<size_t>::max() / mul) { 219 val *= mul; 220 } else { 221 // Clamp to a multiple of 1024. 222 val = std::numeric_limits<size_t>::max() & ~(1024-1); 223 } 224 } else { 225 // There's more than one character after the numeric part. 226 return 0; 227 } 228 } 229 // The man page says that a -Xm value must be a multiple of 1024. 230 if (val % div == 0) { 231 return val; 232 } 233 } 234 } 235 return 0; 236} 237 238size_t ParseIntegerOrDie(const std::string& s) { 239 std::string::size_type colon = s.find(':'); 240 if (colon == std::string::npos) { 241 LOG(FATAL) << "Missing integer: " << s; 242 } 243 const char* begin = &s[colon + 1]; 244 char* end; 245 size_t result = strtoul(begin, &end, 10); 246 if (begin == end || *end != '\0') { 247 LOG(FATAL) << "Failed to parse integer in: " << s; 248 } 249 return result; 250} 251 252void LoadJniLibrary(JavaVMExt* vm, const char* name) { 253 std::string mapped_name(StringPrintf(OS_SHARED_LIB_FORMAT_STR, name)); 254 std::string reason; 255 if (!vm->LoadNativeLibrary(mapped_name, NULL, reason)) { 256 LOG(FATAL) << "LoadNativeLibrary failed for \"" << mapped_name << "\": " 257 << reason; 258 } 259} 260 261Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) { 262 UniquePtr<ParsedOptions> parsed(new ParsedOptions()); 263 const char* boot_class_path = getenv("BOOTCLASSPATH"); 264 if (boot_class_path != NULL) { 265 parsed->boot_class_path_ = boot_class_path; 266 } 267 const char* class_path = getenv("CLASSPATH"); 268 if (class_path != NULL) { 269 parsed->class_path_ = class_path; 270 } 271#ifdef NDEBUG 272 // -Xcheck:jni is off by default for regular builds... 273 parsed->check_jni_ = false; 274#else 275 // ...but on by default in debug builds. 276 parsed->check_jni_ = true; 277#endif 278 279 parsed->heap_initial_size_ = Heap::kInitialSize; 280 parsed->heap_maximum_size_ = Heap::kMaximumSize; 281 parsed->heap_growth_limit_ = 0; // 0 means no growth limit 282 parsed->stack_size_ = Thread::kDefaultStackSize; 283 284 parsed->is_compiler_ = false; 285 parsed->is_zygote_ = false; 286 287 parsed->jni_globals_max_ = 0; 288 parsed->lock_profiling_threshold_ = 0; 289 parsed->hook_is_sensitive_thread_ = NULL; 290 291 parsed->hook_vfprintf_ = vfprintf; 292 parsed->hook_exit_ = exit; 293 parsed->hook_abort_ = abort; 294 295 for (size_t i = 0; i < options.size(); ++i) { 296 const std::string option(options[i].first); 297 if (true && options[0].first == "-Xzygote") { 298 LOG(INFO) << "option[" << i << "]=" << option; 299 } 300 if (StartsWith(option, "-Xbootclasspath:")) { 301 parsed->boot_class_path_ = option.substr(strlen("-Xbootclasspath:")); 302 } else if (option == "-classpath" || option == "-cp") { 303 // TODO: support -Djava.class.path 304 i++; 305 if (i == options.size()) { 306 // TODO: usage 307 LOG(FATAL) << "Missing required class path value for " << option; 308 return NULL; 309 } 310 parsed->class_path_ = options[i].first; 311 } else if (StartsWith(option, "-Ximage:")) { 312 parsed->image_ = option.substr(strlen("-Ximage:")); 313 } else if (StartsWith(option, "-Xcheck:jni")) { 314 parsed->check_jni_ = true; 315 } else if (StartsWith(option, "-Xrunjdwp:") || StartsWith(option, "-agentlib:jdwp=")) { 316 std::string tail(option.substr(option[1] == 'X' ? 10 : 15)); 317 if (tail == "help" || !Dbg::ParseJdwpOptions(tail)) { 318 LOG(FATAL) << "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n" 319 << "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n"; 320 return NULL; 321 } 322 } else if (StartsWith(option, "-Xms")) { 323 size_t size = ParseMemoryOption(option.substr(strlen("-Xms")).c_str(), 1024); 324 if (size == 0) { 325 if (ignore_unrecognized) { 326 continue; 327 } 328 // TODO: usage 329 LOG(FATAL) << "Failed to parse " << option; 330 return NULL; 331 } 332 parsed->heap_initial_size_ = size; 333 } else if (StartsWith(option, "-Xmx")) { 334 size_t size = ParseMemoryOption(option.substr(strlen("-Xmx")).c_str(), 1024); 335 if (size == 0) { 336 if (ignore_unrecognized) { 337 continue; 338 } 339 // TODO: usage 340 LOG(FATAL) << "Failed to parse " << option; 341 return NULL; 342 } 343 parsed->heap_maximum_size_ = size; 344 } else if (StartsWith(option, "-XX:HeapGrowthLimit=")) { 345 size_t size = ParseMemoryOption(option.substr(strlen("-XX:HeapGrowthLimit=")).c_str(), 1024); 346 if (size == 0) { 347 if (ignore_unrecognized) { 348 continue; 349 } 350 // TODO: usage 351 LOG(FATAL) << "Failed to parse " << option; 352 return NULL; 353 } 354 parsed->heap_growth_limit_ = size; 355 } else if (StartsWith(option, "-Xss")) { 356 size_t size = ParseMemoryOption(option.substr(strlen("-Xss")).c_str(), 1); 357 if (size == 0) { 358 if (ignore_unrecognized) { 359 continue; 360 } 361 // TODO: usage 362 LOG(FATAL) << "Failed to parse " << option; 363 return NULL; 364 } 365 parsed->stack_size_ = size; 366 } else if (StartsWith(option, "-D")) { 367 parsed->properties_.push_back(option.substr(strlen("-D"))); 368 } else if (StartsWith(option, "-Xjnitrace:")) { 369 parsed->jni_trace_ = option.substr(strlen("-Xjnitrace:")); 370 } else if (option == "compiler") { 371 parsed->is_compiler_ = true; 372 } else if (option == "-Xzygote") { 373 parsed->is_zygote_ = true; 374 } else if (StartsWith(option, "-verbose:")) { 375 std::vector<std::string> verbose_options; 376 Split(option.substr(strlen("-verbose:")), ',', verbose_options); 377 for (size_t i = 0; i < verbose_options.size(); ++i) { 378 if (verbose_options[i] == "class") { 379 gLogVerbosity.class_linker = true; 380 } else if (verbose_options[i] == "compiler") { 381 gLogVerbosity.compiler = true; 382 } else if (verbose_options[i] == "heap") { 383 gLogVerbosity.heap = true; 384 } else if (verbose_options[i] == "gc") { 385 gLogVerbosity.gc = true; 386 } else if (verbose_options[i] == "jdwp") { 387 gLogVerbosity.jdwp = true; 388 } else if (verbose_options[i] == "jni") { 389 gLogVerbosity.jni = true; 390 } else if (verbose_options[i] == "monitor") { 391 gLogVerbosity.monitor = true; 392 } else if (verbose_options[i] == "startup") { 393 gLogVerbosity.startup = true; 394 } else if (verbose_options[i] == "third-party-jni") { 395 gLogVerbosity.third_party_jni = true; 396 } else if (verbose_options[i] == "threads") { 397 gLogVerbosity.threads = true; 398 } else { 399 LOG(WARNING) << "Ignoring unknown -verbose option: " << verbose_options[i]; 400 } 401 } 402 } else if (StartsWith(option, "-Xjnigreflimit:")) { 403 parsed->jni_globals_max_ = ParseIntegerOrDie(option); 404 } else if (StartsWith(option, "-Xlockprofthreshold:")) { 405 parsed->lock_profiling_threshold_ = ParseIntegerOrDie(option); 406 } else if (StartsWith(option, "-Xstacktracefile:")) { 407// always show stack traces in debug builds 408#ifdef NDEBUG 409 parsed->stack_trace_file_ = option.substr(strlen("-Xstacktracefile:")); 410#endif 411 } else if (option == "sensitiveThread") { 412 parsed->hook_is_sensitive_thread_ = reinterpret_cast<bool (*)()>(options[i].second); 413 } else if (option == "vfprintf") { 414 parsed->hook_vfprintf_ = reinterpret_cast<int (*)(FILE *, const char*, va_list)>(options[i].second); 415 } else if (option == "exit") { 416 parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(options[i].second); 417 } else if (option == "abort") { 418 parsed->hook_abort_ = reinterpret_cast<void(*)()>(options[i].second); 419 } else if (option == "host-prefix") { 420 parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second); 421 } else if (option == "-Xgenregmap" || option == "-Xgc:precise") { 422 // We silently ignore these for backwards compatibility. 423 } else { 424 if (!ignore_unrecognized) { 425 // TODO: print usage via vfprintf 426 LOG(ERROR) << "Unrecognized option " << option; 427 // TODO: this should exit, but for now tolerate unknown options 428 //return NULL; 429 } 430 } 431 } 432 433 if (!parsed->is_compiler_ && parsed->image_.empty()) { 434 parsed->image_ += GetAndroidRoot(); 435 parsed->image_ += "/framework/boot.art"; 436 } 437 if (parsed->heap_growth_limit_ == 0) { 438 parsed->heap_growth_limit_ = parsed->heap_maximum_size_; 439 } 440 441 LOG(INFO) << "Build type: " 442#ifndef NDEBUG 443 << "debug" 444#else 445 << "optimized" 446#endif 447 << "; CheckJNI: " << (parsed->check_jni_ ? "on" : "off"); 448 449 return parsed.release(); 450} 451 452Runtime* Runtime::Create(const Options& options, bool ignore_unrecognized) { 453 // TODO: acquire a static mutex on Runtime to avoid racing. 454 if (Runtime::instance_ != NULL) { 455 return NULL; 456 } 457 instance_ = new Runtime; 458 if (!instance_->Init(options, ignore_unrecognized)) { 459 delete instance_; 460 instance_ = NULL; 461 } 462 return instance_; 463} 464 465void CreateSystemClassLoader() { 466 if (ClassLoader::UseCompileTimeClassPath()) { 467 return; 468 } 469 470 Thread* self = Thread::Current(); 471 472 // Must be in the kNative state for calling native methods. 473 CHECK_EQ(self->GetState(), Thread::kNative); 474 475 JNIEnv* env = self->GetJniEnv(); 476 ScopedLocalRef<jclass> ClassLoader_class(env, env->FindClass("java/lang/ClassLoader")); 477 CHECK(ClassLoader_class.get() != NULL); 478 jmethodID getSystemClassLoader = env->GetStaticMethodID(ClassLoader_class.get(), 479 "getSystemClassLoader", 480 "()Ljava/lang/ClassLoader;"); 481 CHECK(getSystemClassLoader != NULL); 482 ScopedLocalRef<jobject> class_loader(env, env->CallStaticObjectMethod(ClassLoader_class.get(), 483 getSystemClassLoader)); 484 CHECK(class_loader.get() != NULL); 485 486 Thread::Current()->SetClassLoaderOverride(Decode<ClassLoader*>(env, class_loader.get())); 487 488 ScopedLocalRef<jclass> Thread_class(env, env->FindClass("java/lang/Thread")); 489 CHECK(Thread_class.get() != NULL); 490 jfieldID contextClassLoader = env->GetFieldID(Thread_class.get(), 491 "contextClassLoader", 492 "Ljava/lang/ClassLoader;"); 493 CHECK(contextClassLoader != NULL); 494 ScopedLocalRef<jobject> self_jobject(env, AddLocalReference<jobject>(env, self->GetPeer())); 495 env->SetObjectField(self_jobject.get(), contextClassLoader, class_loader.get()); 496} 497 498void Runtime::Start() { 499 VLOG(startup) << "Runtime::Start entering"; 500 501 CHECK(host_prefix_.empty()) << host_prefix_; 502 503 // Restore main thread state to kNative as expected by native code 504 Thread::Current()->SetState(Thread::kNative); 505 506 started_ = true; 507 508 // InitNativeMethods needs to be after started_ so that the classes 509 // it touches will have methods linked to the oat file if necessary. 510 InitNativeMethods(); 511 512 Thread::FinishStartup(); 513 514 if (!is_zygote_) { 515 DidForkFromZygote(); 516 } 517 518 StartDaemonThreads(); 519 520 CreateSystemClassLoader(); 521 522 Thread::Current()->GetJniEnv()->locals.AssertEmpty(); 523 524 VLOG(startup) << "Runtime::Start exiting"; 525} 526 527void Runtime::DidForkFromZygote() { 528 is_zygote_ = false; 529 530 StartSignalCatcher(); 531 532 // Start the JDWP thread. If the command-line debugger flags specified "suspend=y", 533 // this will pause the runtime, so we probably want this to come last. 534 Dbg::StartJdwp(); 535} 536 537void Runtime::StartSignalCatcher() { 538 if (!is_zygote_) { 539 signal_catcher_ = new SignalCatcher(stack_trace_file_); 540 } 541} 542 543void Runtime::StartDaemonThreads() { 544 VLOG(startup) << "Runtime::StartDaemonThreads entering"; 545 546 Thread* self = Thread::Current(); 547 548 // Must be in the kNative state for calling native methods. 549 CHECK_EQ(self->GetState(), Thread::kNative); 550 551 JNIEnv* env = self->GetJniEnv(); 552 ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Daemons")); 553 CHECK(c.get() != NULL); 554 jmethodID mid = env->GetStaticMethodID(c.get(), "start", "()V"); 555 CHECK(mid != NULL); 556 env->CallStaticVoidMethod(c.get(), mid); 557 CHECK(!env->ExceptionCheck()); 558 559 VLOG(startup) << "Runtime::StartDaemonThreads exiting"; 560} 561 562bool Runtime::IsShuttingDown() const { 563 return shutting_down_; 564} 565 566bool Runtime::IsStarted() const { 567 return started_; 568} 569 570bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { 571 CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize); 572 573 UniquePtr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized)); 574 if (options.get() == NULL) { 575 LOG(ERROR) << "Failed to parse options"; 576 return false; 577 } 578 VLOG(startup) << "Runtime::Init -verbose:startup enabled"; 579 580 SetJniGlobalsMax(options->jni_globals_max_); 581 Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_); 582 583 host_prefix_ = options->host_prefix_; 584 boot_class_path_ = options->boot_class_path_; 585 class_path_ = options->class_path_; 586 properties_ = options->properties_; 587 588 is_compiler_ = options->is_compiler_; 589 is_zygote_ = options->is_zygote_; 590 591 vfprintf_ = options->hook_vfprintf_; 592 exit_ = options->hook_exit_; 593 abort_ = options->hook_abort_; 594 595 default_stack_size_ = options->stack_size_; 596 stack_trace_file_ = options->stack_trace_file_; 597 598 monitor_list_ = new MonitorList; 599 thread_list_ = new ThreadList; 600 intern_table_ = new InternTable; 601 602 Heap::Init(options->heap_initial_size_, 603 options->heap_growth_limit_, 604 options->heap_maximum_size_, 605 options->image_); 606 607 BlockSignals(); 608 609 java_vm_ = new JavaVMExt(this, options.get()); 610 611 Thread::Startup(); 612 613 // ClassLinker needs an attached thread, but we can't fully attach a thread 614 // without creating objects. 615 Thread::Attach(this, "main", false); 616 617 // Set us to runnable so tools using a runtime can allocate and GC by default 618 Thread::Current()->SetState(Thread::kRunnable); 619 620 CHECK_GE(Heap::GetSpaces().size(), 1U); 621 class_linker_ = ((Heap::GetSpaces()[0]->IsImageSpace()) 622 ? ClassLinker::Create(intern_table_) 623 : ClassLinker::Create(options->boot_class_path_, intern_table_)); 624 625 VLOG(startup) << "Runtime::Init exiting"; 626 return true; 627} 628 629void Runtime::InitNativeMethods() { 630 VLOG(startup) << "Runtime::InitNativeMethods entering"; 631 Thread* self = Thread::Current(); 632 JNIEnv* env = self->GetJniEnv(); 633 634 // Must be in the kNative state for calling native methods (JNI_OnLoad code). 635 CHECK_EQ(self->GetState(), Thread::kNative); 636 637 // First set up JniConstants, which is used by both the runtime's built-in native 638 // methods and libcore. 639 JniConstants::init(env); 640 641 // Then set up the native methods provided by the runtime itself. 642 RegisterRuntimeNativeMethods(env); 643 644 // Then set up libcore, which is just a regular JNI library with a regular JNI_OnLoad. 645 // Most JNI libraries can just use System.loadLibrary, but libcore can't because it's 646 // the library that implements System.loadLibrary! 647 LoadJniLibrary(instance_->GetJavaVM(), "javacore"); 648 VLOG(startup) << "Runtime::InitNativeMethods exiting"; 649} 650 651void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) { 652#define REGISTER(FN) extern void FN(JNIEnv*); FN(env) 653 // Register Throwable first so that registration of other native methods can throw exceptions 654 REGISTER(register_java_lang_Throwable); 655 REGISTER(register_dalvik_system_DexFile); 656 REGISTER(register_dalvik_system_VMDebug); 657 REGISTER(register_dalvik_system_VMRuntime); 658 REGISTER(register_dalvik_system_VMStack); 659 REGISTER(register_dalvik_system_Zygote); 660 REGISTER(register_java_lang_Class); 661 REGISTER(register_java_lang_Object); 662 REGISTER(register_java_lang_Runtime); 663 REGISTER(register_java_lang_String); 664 REGISTER(register_java_lang_System); 665 REGISTER(register_java_lang_Thread); 666 REGISTER(register_java_lang_VMClassLoader); 667 REGISTER(register_java_lang_reflect_Array); 668 REGISTER(register_java_lang_reflect_Constructor); 669 REGISTER(register_java_lang_reflect_Field); 670 REGISTER(register_java_lang_reflect_Method); 671 REGISTER(register_java_lang_reflect_Proxy); 672 REGISTER(register_java_util_concurrent_atomic_AtomicLong); 673 REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer); 674 REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal); 675 REGISTER(register_sun_misc_Unsafe); 676#undef REGISTER 677} 678 679void Runtime::Dump(std::ostream& os) { 680 // TODO: dump other runtime statistics? 681 GetClassLinker()->DumpForSigQuit(os); 682 GetInternTable()->DumpForSigQuit(os); 683 os << "\n"; 684 685 thread_list_->Dump(os); 686} 687 688void Runtime::DumpLockHolders(std::ostream& os) { 689 pid_t heap_lock_owner = Heap::GetLockOwner(); 690 pid_t thread_list_lock_owner = GetThreadList()->GetLockOwner(); 691 pid_t classes_lock_owner = GetClassLinker()->GetClassesLockOwner(); 692 pid_t dex_lock_owner = GetClassLinker()->GetDexLockOwner(); 693 if ((heap_lock_owner | thread_list_lock_owner | classes_lock_owner | dex_lock_owner) != 0) { 694 os << "Heap lock owner tid: " << heap_lock_owner << "\n" 695 << "ThreadList lock owner tid: " << thread_list_lock_owner << "\n" 696 << "ClassLinker classes lock owner tid: " << classes_lock_owner << "\n" 697 << "ClassLinker dex lock owner tid: " << dex_lock_owner << "\n"; 698 } 699} 700 701void Runtime::SetStatsEnabled(bool new_state) { 702 if (new_state == true) { 703 GetStats()->Clear(~0); 704 // TODO: wouldn't it make more sense to clear _all_ threads' stats? 705 Thread::Current()->GetStats()->Clear(~0); 706 } 707 stats_enabled_ = new_state; 708} 709 710void Runtime::ResetStats(int kinds) { 711 GetStats()->Clear(kinds & 0xffff); 712 // TODO: wouldn't it make more sense to clear _all_ threads' stats? 713 Thread::Current()->GetStats()->Clear(kinds >> 16); 714} 715 716RuntimeStats* Runtime::GetStats() { 717 return &stats_; 718} 719 720int32_t Runtime::GetStat(int kind) { 721 RuntimeStats* stats; 722 if (kind < (1<<16)) { 723 stats = GetStats(); 724 } else { 725 stats = Thread::Current()->GetStats(); 726 kind >>= 16; 727 } 728 switch (kind) { 729 case KIND_ALLOCATED_OBJECTS: 730 return stats->allocated_objects; 731 case KIND_ALLOCATED_BYTES: 732 return stats->allocated_bytes; 733 case KIND_FREED_OBJECTS: 734 return stats->freed_objects; 735 case KIND_FREED_BYTES: 736 return stats->freed_bytes; 737 case KIND_GC_INVOCATIONS: 738 return stats->gc_for_alloc_count; 739 case KIND_CLASS_INIT_COUNT: 740 return stats->class_init_count; 741 case KIND_CLASS_INIT_TIME: 742 // Convert ns to us, reduce to 32 bits. 743 return (int) (stats->class_init_time_ns / 1000); 744 case KIND_EXT_ALLOCATED_OBJECTS: 745 case KIND_EXT_ALLOCATED_BYTES: 746 case KIND_EXT_FREED_OBJECTS: 747 case KIND_EXT_FREED_BYTES: 748 return 0; // backward compatibility 749 default: 750 CHECK(false); 751 return -1; // unreachable 752 } 753} 754 755void Runtime::BlockSignals() { 756 sigset_t sigset; 757 if (sigemptyset(&sigset) == -1) { 758 PLOG(FATAL) << "sigemptyset failed"; 759 } 760 if (sigaddset(&sigset, SIGPIPE) == -1) { 761 PLOG(ERROR) << "sigaddset SIGPIPE failed"; 762 } 763 // SIGQUIT is used to dump the runtime's state (including stack traces). 764 if (sigaddset(&sigset, SIGQUIT) == -1) { 765 PLOG(ERROR) << "sigaddset SIGQUIT failed"; 766 } 767 // SIGUSR1 is used to initiate a heap dump. 768 if (sigaddset(&sigset, SIGUSR1) == -1) { 769 PLOG(ERROR) << "sigaddset SIGUSR1 failed"; 770 } 771 CHECK_EQ(sigprocmask(SIG_BLOCK, &sigset, NULL), 0); 772} 773 774void Runtime::AttachCurrentThread(const char* name, bool as_daemon) { 775 Thread::Attach(instance_, name, as_daemon); 776} 777 778void Runtime::DetachCurrentThread() { 779 // TODO: check we're not calling DetachCurrentThread from a call stack that 780 // includes managed frames. (It's only valid if the stack is all-native.) 781 thread_list_->Unregister(); 782} 783 784void Runtime::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { 785 Dbg::VisitRoots(visitor, arg); 786 class_linker_->VisitRoots(visitor, arg); 787 intern_table_->VisitRoots(visitor, arg); 788 java_vm_->VisitRoots(visitor, arg); 789 thread_list_->VisitRoots(visitor, arg); 790 visitor(jni_stub_array_, arg); 791 visitor(abstract_method_error_stub_array_, arg); 792 for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) { 793 visitor(resolution_stub_array_[i], arg); 794 } 795 for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 796 visitor(callee_save_method_[i], arg); 797 } 798} 799 800bool Runtime::HasJniDlsymLookupStub() const { 801 return jni_stub_array_ != NULL; 802} 803 804ByteArray* Runtime::GetJniDlsymLookupStub() const { 805 CHECK(jni_stub_array_ != NULL); 806 return jni_stub_array_; 807} 808 809void Runtime::SetJniDlsymLookupStub(ByteArray* jni_stub_array) { 810 CHECK(jni_stub_array != NULL) << " jni_stub_array=" << jni_stub_array; 811 CHECK(jni_stub_array_ == NULL || jni_stub_array_ == jni_stub_array) 812 << "jni_stub_array_=" << jni_stub_array_ << " jni_stub_array=" << jni_stub_array; 813 jni_stub_array_ = jni_stub_array; 814} 815 816bool Runtime::HasAbstractMethodErrorStubArray() const { 817 return abstract_method_error_stub_array_ != NULL; 818} 819 820ByteArray* Runtime::GetAbstractMethodErrorStubArray() const { 821 CHECK(abstract_method_error_stub_array_ != NULL); 822 return abstract_method_error_stub_array_; 823} 824 825void Runtime::SetAbstractMethodErrorStubArray(ByteArray* abstract_method_error_stub_array) { 826 CHECK(abstract_method_error_stub_array != NULL); 827 CHECK(abstract_method_error_stub_array_ == NULL || abstract_method_error_stub_array_ == abstract_method_error_stub_array); 828 abstract_method_error_stub_array_ = abstract_method_error_stub_array; 829} 830 831 832Runtime::TrampolineType Runtime::GetTrampolineType(Method* method) { 833 if (method == NULL) { 834 return Runtime::kUnknownMethod; 835 } else if (method->IsStatic()) { 836 return Runtime::kStaticMethod; 837 } else { 838 return Runtime::kInstanceMethod; 839 } 840} 841 842bool Runtime::HasResolutionStubArray(TrampolineType type) const { 843 return resolution_stub_array_[type] != NULL; 844} 845 846ByteArray* Runtime::GetResolutionStubArray(TrampolineType type) const { 847 CHECK(HasResolutionStubArray(type)); 848 DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastTrampolineMethodType)); 849 return resolution_stub_array_[type]; 850} 851 852void Runtime::SetResolutionStubArray(ByteArray* resolution_stub_array, TrampolineType type) { 853 CHECK(resolution_stub_array != NULL); 854 CHECK(!HasResolutionStubArray(type) || resolution_stub_array_[type] == resolution_stub_array); 855 resolution_stub_array_[type] = resolution_stub_array; 856} 857 858Method* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) { 859 Class* method_class = Method::GetMethodClass(); 860 SirtRef<Method> method(down_cast<Method*>(method_class->AllocObject())); 861 method->SetDeclaringClass(method_class); 862 // TODO: use a special method for callee saves 863 method->SetMethodIndex(DexFile::kDexNoIndex16); 864 method->SetCode(NULL); 865 if ((instruction_set == kThumb2) || (instruction_set == kArm)) { 866 uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6) | (1 << art::arm::R7) | 867 (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11); 868 uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3); 869 uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9); 870 uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills :0) | 871 (type == kSaveAll ? all_spills :0) | (1 << art::arm::LR); 872 uint32_t fp_all_spills = (1 << art::arm::S0) | (1 << art::arm::S1) | (1 << art::arm::S2) | 873 (1 << art::arm::S3) | (1 << art::arm::S4) | (1 << art::arm::S5) | 874 (1 << art::arm::S6) | (1 << art::arm::S7) | (1 << art::arm::S8) | 875 (1 << art::arm::S9) | (1 << art::arm::S10) | (1 << art::arm::S11) | 876 (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) | 877 (1 << art::arm::S15) | (1 << art::arm::S16) | (1 << art::arm::S17) | 878 (1 << art::arm::S18) | (1 << art::arm::S19) | (1 << art::arm::S20) | 879 (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) | 880 (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) | 881 (1 << art::arm::S27) | (1 << art::arm::S28) | (1 << art::arm::S29) | 882 (1 << art::arm::S30) | (1 << art::arm::S31); 883 uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0; 884 size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ + 885 __builtin_popcount(fp_spills) /* fprs */ + 886 1 /* Method* */) * kPointerSize, kStackAlignment); 887 method->SetFrameSizeInBytes(frame_size); 888 method->SetCoreSpillMask(core_spills); 889 method->SetFpSpillMask(fp_spills); 890 } else if (instruction_set == kX86) { 891 method->SetFrameSizeInBytes(32); 892 method->SetCoreSpillMask((1 << art::x86::EBX) | (1 << art::x86::EBP) | (1 << art::x86::ESI) | 893 (1 << art::x86::EDI)); 894 method->SetFpSpillMask(0); 895 } else { 896 UNIMPLEMENTED(FATAL); 897 } 898 return method.get(); 899} 900 901bool Runtime::HasCalleeSaveMethod(CalleeSaveType type) const { 902 return callee_save_method_[type] != NULL; 903} 904 905// Returns a special method that describes all callee saves being spilled to the stack. 906Method* Runtime::GetCalleeSaveMethod(CalleeSaveType type) const { 907 CHECK(HasCalleeSaveMethod(type)); 908 return callee_save_method_[type]; 909} 910 911void Runtime::SetCalleeSaveMethod(Method* method, CalleeSaveType type) { 912 DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType)); 913 callee_save_method_[type] = method; 914} 915 916void Runtime::EnableMethodTracing(Trace* tracer) { 917 CHECK(!IsMethodTracingActive()); 918 tracer_ = tracer; 919} 920 921void Runtime::DisableMethodTracing() { 922 CHECK(IsMethodTracingActive()); 923 delete tracer_; 924 tracer_ = NULL; 925} 926 927bool Runtime::IsMethodTracingActive() const { 928 return (tracer_ != NULL); 929} 930 931Trace* Runtime::GetTracer() const { 932 CHECK(IsMethodTracingActive()); 933 return tracer_; 934} 935 936} // namespace art 937