1 /* 2 * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <ctype.h> 27 28 #include "util.h" 29 #include "commonRef.h" 30 #include "debugDispatch.h" 31 #include "eventHandler.h" 32 #include "eventHelper.h" 33 #include "threadControl.h" 34 #include "stepControl.h" 35 #include "transport.h" 36 #include "classTrack.h" 37 #include "debugLoop.h" 38 #include "bag.h" 39 #include "invoker.h" 40 #include "sys.h" 41 42 /* How the options get to OnLoad: */ 43 #define XDEBUG "-Xdebug" 44 #define XRUN "-Xrunjdwp" 45 #define AGENTLIB "-agentlib:jdwp" 46 47 /* Debug version defaults */ 48 #ifdef DEBUG 49 #define DEFAULT_ASSERT_ON JNI_TRUE 50 #define DEFAULT_ASSERT_FATAL JNI_TRUE 51 #define DEFAULT_LOGFILE "jdwp.log" 52 #else 53 #define DEFAULT_ASSERT_ON JNI_FALSE 54 #define DEFAULT_ASSERT_FATAL JNI_FALSE 55 #define DEFAULT_LOGFILE NULL 56 #endif 57 58 static jboolean vmInitialized; 59 static jrawMonitorID initMonitor; 60 static jboolean initComplete; 61 static jbyte currentSessionID; 62 63 /* 64 * Options set through the OnLoad options string. All of these values 65 * are set once at VM startup and never reset. 66 */ 67 static jboolean isServer = JNI_FALSE; /* Listens for connecting debuggers? */ 68 static jboolean isStrict = JNI_FALSE; /* Unused */ 69 static jboolean useStandardAlloc = JNI_FALSE; /* Use standard malloc/free? */ 70 static struct bag *transports; /* of TransportSpec */ 71 72 static jboolean initOnStartup = JNI_TRUE; /* init immediately */ 73 static char *initOnException = NULL; /* init when this exception thrown */ 74 static jboolean initOnUncaught = JNI_FALSE; /* init when uncaught exc thrown */ 75 76 static char *launchOnInit = NULL; /* launch this app during init */ 77 static jboolean suspendOnInit = JNI_TRUE; /* suspend all app threads after init */ 78 static jboolean dopause = JNI_FALSE; /* pause for debugger attach */ 79 static jboolean docoredump = JNI_FALSE; /* core dump on exit */ 80 static char *logfile = NULL; /* Name of logfile (if logging) */ 81 static unsigned logflags = 0; /* Log flags */ 82 83 static char *names; /* strings derived from OnLoad options */ 84 85 /* 86 * Elements of the transports bag 87 */ 88 typedef struct TransportSpec { 89 char *name; 90 char *address; 91 long timeout; 92 } TransportSpec; 93 94 /* 95 * Forward Refs 96 */ 97 static void JNICALL cbEarlyVMInit(jvmtiEnv*, JNIEnv *, jthread); 98 static void JNICALL cbEarlyVMDeath(jvmtiEnv*, JNIEnv *); 99 static void JNICALL cbEarlyException(jvmtiEnv*, JNIEnv *, 100 jthread, jmethodID, jlocation, jobject, jmethodID, jlocation); 101 102 static void initialize(JNIEnv *env, jthread thread, EventIndex triggering_ei); 103 static jboolean parseOptions(char *str); 104 105 /* 106 * Phase 1: Initial load. 107 * 108 * OnLoad is called by the VM immediately after the back-end 109 * library is loaded. We can do very little in this function since 110 * the VM has not completed initialization. So, we parse the JDWP 111 * options and set up a simple initial event callbacks for JVMTI events. 112 * When a triggering event occurs, that callback will begin debugger initialization. 113 */ 114 115 /* Get a static area to hold the Global Data */ 116 static BackendGlobalData * 117 get_gdata(void) 118 { 119 static BackendGlobalData s; 120 (void)memset(&s, 0, sizeof(BackendGlobalData)); 121 return &s; 122 } 123 124 static jvmtiError 125 set_event_notification(jvmtiEventMode mode, EventIndex ei) 126 { 127 jvmtiError error; 128 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode) 129 (gdata->jvmti, mode, eventIndex2jvmti(ei), NULL); 130 if (error != JVMTI_ERROR_NONE) { 131 ERROR_MESSAGE(("JDWP unable to configure initial JVMTI event %s: %s(%d)", 132 eventText(ei), jvmtiErrorText(error), error)); 133 } 134 return error; 135 } 136 137 typedef struct { 138 int major; 139 int minor; 140 } version_type; 141 142 typedef struct { 143 version_type runtime; 144 version_type compiletime; 145 } compatible_versions_type; 146 147 /* 148 * List of explicitly compatible JVMTI versions, specified as 149 * { runtime version, compile-time version } pairs. -1 is a wildcard. 150 */ 151 static int nof_compatible_versions = 3; 152 static compatible_versions_type compatible_versions_list[] = { 153 /* 154 * FIXUP: Allow version 0 to be compatible with anything 155 * Special check for FCS of 1.0. 156 */ 157 { { 0, -1 }, { -1, -1 } }, 158 { { -1, -1 }, { 0, -1 } }, 159 /* 160 * 1.2 is runtime compatible with 1.1 -- just make sure to check the 161 * version before using any new 1.2 features 162 */ 163 { { 1, 1 }, { 1, 2 } } 164 }; 165 166 167 /* Logic to determine JVMTI version compatibility */ 168 static jboolean 169 compatible_versions(jint major_runtime, jint minor_runtime, 170 jint major_compiletime, jint minor_compiletime) 171 { 172 /* 173 * First check to see if versions are explicitly compatible via the 174 * list specified above. 175 */ 176 int i; 177 for (i = 0; i < nof_compatible_versions; ++i) { 178 version_type runtime = compatible_versions_list[i].runtime; 179 version_type comptime = compatible_versions_list[i].compiletime; 180 181 if ((major_runtime == runtime.major || runtime.major == -1) && 182 (minor_runtime == runtime.minor || runtime.minor == -1) && 183 (major_compiletime == comptime.major || comptime.major == -1) && 184 (minor_compiletime == comptime.minor || comptime.minor == -1)) { 185 return JNI_TRUE; 186 } 187 } 188 189 return major_runtime == major_compiletime && 190 minor_runtime >= minor_compiletime; 191 } 192 193 /* OnLoad startup: 194 * Returning JNI_ERR will cause the java_g VM to core dump, be careful. 195 */ 196 JNIEXPORT jint JNICALL 197 Agent_OnLoad(JavaVM *vm, char *options, void *reserved) 198 { 199 jvmtiError error; 200 jvmtiCapabilities needed_capabilities; 201 jvmtiCapabilities potential_capabilities; 202 jint jvmtiCompileTimeMajorVersion; 203 jint jvmtiCompileTimeMinorVersion; 204 jint jvmtiCompileTimeMicroVersion; 205 char *boot_path = NULL; 206 char npt_lib[MAXPATHLEN]; 207 208 /* See if it's already loaded */ 209 if ( gdata!=NULL && gdata->isLoaded==JNI_TRUE ) { 210 ERROR_MESSAGE(("Cannot load this JVM TI agent twice, check your java command line for duplicate jdwp options.")); 211 return JNI_ERR; 212 } 213 214 /* If gdata is defined and the VM died, why are we here? */ 215 if ( gdata!=NULL && gdata->vmDead ) { 216 ERROR_MESSAGE(("JDWP unable to load, VM died")); 217 return JNI_ERR; 218 } 219 220 /* Get global data area */ 221 gdata = get_gdata(); 222 if (gdata == NULL) { 223 ERROR_MESSAGE(("JDWP unable to allocate memory")); 224 return JNI_ERR; 225 } 226 gdata->isLoaded = JNI_TRUE; 227 228 /* Start filling in gdata */ 229 gdata->jvm = vm; 230 vmInitialized = JNI_FALSE; 231 gdata->vmDead = JNI_FALSE; 232 233 /* Get the JVMTI Env, IMPORTANT: Do this first! For jvmtiAllocate(). */ 234 error = JVM_FUNC_PTR(vm,GetEnv) 235 (vm, (void **)&(gdata->jvmti), JVMTI_VERSION_1); 236 if (error != JNI_OK) { 237 ERROR_MESSAGE(("JDWP unable to access JVMTI Version 1 (0x%x)," 238 " is your J2SE a 1.5 or newer version?" 239 " JNIEnv's GetEnv() returned %d", 240 JVMTI_VERSION_1, error)); 241 forceExit(1); /* Kill entire process, no core dump */ 242 } 243 244 /* Check to make sure the version of jvmti.h we compiled with 245 * matches the runtime version we are using. 246 */ 247 jvmtiCompileTimeMajorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MAJOR ) 248 >> JVMTI_VERSION_SHIFT_MAJOR; 249 jvmtiCompileTimeMinorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MINOR ) 250 >> JVMTI_VERSION_SHIFT_MINOR; 251 jvmtiCompileTimeMicroVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MICRO ) 252 >> JVMTI_VERSION_SHIFT_MICRO; 253 254 /* Check for compatibility */ 255 if ( !compatible_versions(jvmtiMajorVersion(), jvmtiMinorVersion(), 256 jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion) ) { 257 258 ERROR_MESSAGE(("This jdwp native library will not work with this VM's " 259 "version of JVMTI (%d.%d.%d), it needs JVMTI %d.%d[.%d].", 260 jvmtiMajorVersion(), 261 jvmtiMinorVersion(), 262 jvmtiMicroVersion(), 263 jvmtiCompileTimeMajorVersion, 264 jvmtiCompileTimeMinorVersion, 265 jvmtiCompileTimeMicroVersion)); 266 267 /* Do not let VM get a fatal error, we don't want a core dump here. */ 268 forceExit(1); /* Kill entire process, no core dump wanted */ 269 } 270 271 JVMTI_FUNC_PTR(gdata->jvmti, GetSystemProperty) 272 (gdata->jvmti, (const char *)"sun.boot.library.path", 273 &boot_path); 274 275 dbgsysBuildLibName(npt_lib, sizeof(npt_lib), boot_path, NPT_LIBNAME); 276 /* Npt and Utf function init */ 277 NPT_INITIALIZE(npt_lib, &(gdata->npt), NPT_VERSION, NULL); 278 jvmtiDeallocate(boot_path); 279 if (gdata->npt == NULL) { 280 ERROR_MESSAGE(("JDWP: unable to initialize NPT library")); 281 return JNI_ERR; 282 } 283 gdata->npt->utf = (gdata->npt->utfInitialize)(NULL); 284 if (gdata->npt->utf == NULL) { 285 ERROR_MESSAGE(("JDWP: UTF function initialization failed")); 286 return JNI_ERR; 287 } 288 289 /* Parse input options */ 290 if (!parseOptions(options)) { 291 /* No message necessary, should have been printed out already */ 292 /* Do not let VM get a fatal error, we don't want a core dump here. */ 293 forceExit(1); /* Kill entire process, no core dump wanted */ 294 } 295 296 LOG_MISC(("Onload: %s", options)); 297 298 /* Get potential capabilities */ 299 (void)memset(&potential_capabilities,0,sizeof(potential_capabilities)); 300 error = JVMTI_FUNC_PTR(gdata->jvmti,GetPotentialCapabilities) 301 (gdata->jvmti, &potential_capabilities); 302 if (error != JVMTI_ERROR_NONE) { 303 ERROR_MESSAGE(("JDWP unable to get potential JVMTI capabilities: %s(%d)", 304 jvmtiErrorText(error), error)); 305 return JNI_ERR; 306 } 307 308 /* Fill in ones that we must have */ 309 (void)memset(&needed_capabilities,0,sizeof(needed_capabilities)); 310 needed_capabilities.can_access_local_variables = 1; 311 needed_capabilities.can_generate_single_step_events = 1; 312 needed_capabilities.can_generate_exception_events = 1; 313 needed_capabilities.can_generate_frame_pop_events = 1; 314 needed_capabilities.can_generate_breakpoint_events = 1; 315 needed_capabilities.can_suspend = 1; 316 needed_capabilities.can_generate_method_entry_events = 1; 317 needed_capabilities.can_generate_method_exit_events = 1; 318 needed_capabilities.can_generate_garbage_collection_events = 1; 319 needed_capabilities.can_maintain_original_method_order = 1; 320 needed_capabilities.can_generate_monitor_events = 1; 321 needed_capabilities.can_tag_objects = 1; 322 323 /* And what potential ones that would be nice to have */ 324 needed_capabilities.can_force_early_return 325 = potential_capabilities.can_force_early_return; 326 needed_capabilities.can_generate_field_modification_events 327 = potential_capabilities.can_generate_field_modification_events; 328 needed_capabilities.can_generate_field_access_events 329 = potential_capabilities.can_generate_field_access_events; 330 needed_capabilities.can_get_bytecodes 331 = potential_capabilities.can_get_bytecodes; 332 needed_capabilities.can_get_synthetic_attribute 333 = potential_capabilities.can_get_synthetic_attribute; 334 needed_capabilities.can_get_owned_monitor_info 335 = potential_capabilities.can_get_owned_monitor_info; 336 needed_capabilities.can_get_current_contended_monitor 337 = potential_capabilities.can_get_current_contended_monitor; 338 needed_capabilities.can_get_monitor_info 339 = potential_capabilities.can_get_monitor_info; 340 needed_capabilities.can_pop_frame 341 = potential_capabilities.can_pop_frame; 342 needed_capabilities.can_redefine_classes 343 = potential_capabilities.can_redefine_classes; 344 needed_capabilities.can_redefine_any_class 345 = potential_capabilities.can_redefine_any_class; 346 needed_capabilities.can_get_owned_monitor_stack_depth_info 347 = potential_capabilities.can_get_owned_monitor_stack_depth_info; 348 needed_capabilities.can_get_constant_pool 349 = potential_capabilities.can_get_constant_pool; 350 { 351 needed_capabilities.can_get_source_debug_extension = 1; 352 needed_capabilities.can_get_source_file_name = 1; 353 needed_capabilities.can_get_line_numbers = 1; 354 needed_capabilities.can_signal_thread 355 = potential_capabilities.can_signal_thread; 356 } 357 358 /* Add the capabilities */ 359 error = JVMTI_FUNC_PTR(gdata->jvmti,AddCapabilities) 360 (gdata->jvmti, &needed_capabilities); 361 if (error != JVMTI_ERROR_NONE) { 362 ERROR_MESSAGE(("JDWP unable to get necessary JVMTI capabilities.")); 363 forceExit(1); /* Kill entire process, no core dump wanted */ 364 } 365 366 /* Initialize event number mapping tables */ 367 eventIndexInit(); 368 369 /* Set the initial JVMTI event notifications */ 370 error = set_event_notification(JVMTI_ENABLE, EI_VM_DEATH); 371 if (error != JVMTI_ERROR_NONE) { 372 return JNI_ERR; 373 } 374 error = set_event_notification(JVMTI_ENABLE, EI_VM_INIT); 375 if (error != JVMTI_ERROR_NONE) { 376 return JNI_ERR; 377 } 378 if (initOnUncaught || (initOnException != NULL)) { 379 error = set_event_notification(JVMTI_ENABLE, EI_EXCEPTION); 380 if (error != JVMTI_ERROR_NONE) { 381 return JNI_ERR; 382 } 383 } 384 385 /* Set callbacks just for 3 functions */ 386 (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks)); 387 gdata->callbacks.VMInit = &cbEarlyVMInit; 388 gdata->callbacks.VMDeath = &cbEarlyVMDeath; 389 gdata->callbacks.Exception = &cbEarlyException; 390 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks) 391 (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks)); 392 if (error != JVMTI_ERROR_NONE) { 393 ERROR_MESSAGE(("JDWP unable to set JVMTI event callbacks: %s(%d)", 394 jvmtiErrorText(error), error)); 395 return JNI_ERR; 396 } 397 398 LOG_MISC(("OnLoad: DONE")); 399 return JNI_OK; 400 } 401 402 JNIEXPORT void JNICALL 403 Agent_OnUnload(JavaVM *vm) 404 { 405 406 gdata->isLoaded = JNI_FALSE; 407 408 /* Cleanup, but make sure VM is alive before using JNI, and 409 * make sure JVMTI environment is ok before deallocating 410 * memory allocated through JVMTI, which all of it is. 411 */ 412 413 /* 414 * Close transport before exit 415 */ 416 if (transport_is_open()) { 417 transport_close(); 418 } 419 } 420 421 /* 422 * Phase 2: Initial events. Phase 2 consists of waiting for the 423 * event that triggers full initialization. Under normal circumstances 424 * (initOnStartup == TRUE) this is the JVMTI_EVENT_VM_INIT event. 425 * Otherwise, we delay initialization until the app throws a 426 * particular exception. The triggering event invokes 427 * the bulk of the initialization, including creation of threads and 428 * monitors, transport setup, and installation of a new event callback which 429 * handles the complete set of events. 430 * 431 * Since the triggering event comes in on an application thread, some of the 432 * initialization is difficult to do here. Specifically, this thread along 433 * with all other app threads may need to be suspended until a debugger 434 * connects. These kinds of tasks are left to the third phase which is 435 * invoked by one of the spawned debugger threads, the event handler. 436 */ 437 438 /* 439 * Wait for a triggering event; then kick off debugger 440 * initialization. A different event callback will be installed by 441 * debugger initialization, and this function will not be called 442 * again. 443 */ 444 445 /* 446 * TO DO: Decide whether we need to protect this code with 447 * a lock. It might be too early to create a monitor safely (?). 448 */ 449 450 static void JNICALL 451 cbEarlyVMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) 452 { 453 LOG_CB(("cbEarlyVMInit")); 454 if ( gdata->vmDead ) { 455 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at VM_INIT time"); 456 } 457 if (initOnStartup) 458 initialize(env, thread, EI_VM_INIT); 459 vmInitialized = JNI_TRUE; 460 LOG_MISC(("END cbEarlyVMInit")); 461 } 462 463 static void 464 disposeEnvironment(jvmtiEnv *jvmti_env) 465 { 466 jvmtiError error; 467 468 error = JVMTI_FUNC_PTR(jvmti_env,DisposeEnvironment)(jvmti_env); 469 if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY ) 470 error = JVMTI_ERROR_NONE; /* Hack! FIXUP when JVMTI has disposeEnv */ 471 /* What should error return say? */ 472 if (error != JVMTI_ERROR_NONE) { 473 ERROR_MESSAGE(("JDWP unable to dispose of JVMTI environment: %s(%d)", 474 jvmtiErrorText(error), error)); 475 } 476 gdata->jvmti = NULL; 477 } 478 479 static void JNICALL 480 cbEarlyVMDeath(jvmtiEnv *jvmti_env, JNIEnv *env) 481 { 482 LOG_CB(("cbEarlyVMDeath")); 483 if ( gdata->vmDead ) { 484 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM died more than once"); 485 } 486 disposeEnvironment(jvmti_env); 487 gdata->jvmti = NULL; 488 gdata->jvm = NULL; 489 gdata->vmDead = JNI_TRUE; 490 LOG_MISC(("END cbEarlyVMDeath")); 491 } 492 493 static void JNICALL 494 cbEarlyException(jvmtiEnv *jvmti_env, JNIEnv *env, 495 jthread thread, jmethodID method, jlocation location, 496 jobject exception, 497 jmethodID catch_method, jlocation catch_location) 498 { 499 jvmtiError error; 500 jthrowable currentException; 501 502 LOG_CB(("cbEarlyException: thread=%p", thread)); 503 504 if ( gdata->vmDead ) { 505 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at initial Exception event"); 506 } 507 if (!vmInitialized) { 508 LOG_MISC(("VM is not initialized yet")); 509 return; 510 } 511 512 /* 513 * We want to preserve any current exception that might get wiped 514 * out during event handling (e.g. JNI calls). We have to rely on 515 * space for the local reference on the current frame because 516 * doing a PushLocalFrame here might itself generate an exception. 517 */ 518 519 currentException = JNI_FUNC_PTR(env,ExceptionOccurred)(env); 520 JNI_FUNC_PTR(env,ExceptionClear)(env); 521 522 if (initOnUncaught && catch_method == NULL) { 523 524 LOG_MISC(("Initializing on uncaught exception")); 525 initialize(env, thread, EI_EXCEPTION); 526 527 } else if (initOnException != NULL) { 528 529 jclass clazz; 530 531 /* Get class of exception thrown */ 532 clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, exception); 533 if ( clazz != NULL ) { 534 char *signature = NULL; 535 /* initing on throw, check */ 536 error = classSignature(clazz, &signature, NULL); 537 LOG_MISC(("Checking specific exception: looking for %s, got %s", 538 initOnException, signature)); 539 if ( (error==JVMTI_ERROR_NONE) && 540 (strcmp(signature, initOnException) == 0)) { 541 LOG_MISC(("Initializing on specific exception")); 542 initialize(env, thread, EI_EXCEPTION); 543 } else { 544 error = AGENT_ERROR_INTERNAL; /* Just to cause restore */ 545 } 546 if ( signature != NULL ) { 547 jvmtiDeallocate(signature); 548 } 549 } else { 550 error = AGENT_ERROR_INTERNAL; /* Just to cause restore */ 551 } 552 553 /* If initialize didn't happen, we need to restore things */ 554 if ( error != JVMTI_ERROR_NONE ) { 555 /* 556 * Restore exception state from before callback call 557 */ 558 LOG_MISC(("No initialization, didn't find right exception")); 559 if (currentException != NULL) { 560 JNI_FUNC_PTR(env,Throw)(env, currentException); 561 } else { 562 JNI_FUNC_PTR(env,ExceptionClear)(env); 563 } 564 } 565 566 } 567 568 LOG_MISC(("END cbEarlyException")); 569 570 } 571 572 typedef struct EnumerateArg { 573 jboolean isServer; 574 jdwpError error; 575 jint startCount; 576 } EnumerateArg; 577 578 static jboolean 579 startTransport(void *item, void *arg) 580 { 581 TransportSpec *transport = item; 582 EnumerateArg *enumArg = arg; 583 jdwpError serror; 584 585 LOG_MISC(("Begin startTransport")); 586 serror = transport_startTransport(enumArg->isServer, transport->name, 587 transport->address, transport->timeout); 588 if (serror != JDWP_ERROR(NONE)) { 589 ERROR_MESSAGE(("JDWP Transport %s failed to initialize, %s(%d)", 590 transport->name, jdwpErrorText(serror), serror)); 591 enumArg->error = serror; 592 } else { 593 /* (Don't overwrite any previous error) */ 594 595 enumArg->startCount++; 596 } 597 598 LOG_MISC(("End startTransport")); 599 600 return JNI_TRUE; /* Always continue, even if there was an error */ 601 } 602 603 static void 604 signalInitComplete(void) 605 { 606 /* 607 * Initialization is complete 608 */ 609 LOG_MISC(("signal initialization complete")); 610 debugMonitorEnter(initMonitor); 611 initComplete = JNI_TRUE; 612 debugMonitorNotifyAll(initMonitor); 613 debugMonitorExit(initMonitor); 614 } 615 616 /* 617 * Determine if initialization is complete. 618 */ 619 jboolean 620 debugInit_isInitComplete(void) 621 { 622 return initComplete; 623 } 624 625 /* 626 * Wait for all initialization to complete. 627 */ 628 void 629 debugInit_waitInitComplete(void) 630 { 631 debugMonitorEnter(initMonitor); 632 while (!initComplete) { 633 debugMonitorWait(initMonitor); 634 } 635 debugMonitorExit(initMonitor); 636 } 637 638 /* All process exit() calls come from here */ 639 void 640 forceExit(int exit_code) 641 { 642 /* make sure the transport is closed down before we exit() */ 643 transport_close(); 644 exit(exit_code); 645 } 646 647 /* All JVM fatal error exits lead here (e.g. we need to kill the VM). */ 648 static void 649 jniFatalError(JNIEnv *env, const char *msg, jvmtiError error, int exit_code) 650 { 651 JavaVM *vm; 652 char buf[512]; 653 654 gdata->vmDead = JNI_TRUE; 655 if ( msg==NULL ) 656 msg = "UNKNOWN REASON"; 657 vm = gdata->jvm; 658 if ( env==NULL && vm!=NULL ) { 659 jint rc = (*((*vm)->GetEnv))(vm, (void **)&env, JNI_VERSION_1_2); 660 if (rc != JNI_OK ) { 661 env = NULL; 662 } 663 } 664 if ( error != JVMTI_ERROR_NONE ) { 665 (void)snprintf(buf, sizeof(buf), "JDWP %s, jvmtiError=%s(%d)", 666 msg, jvmtiErrorText(error), error); 667 } else { 668 (void)snprintf(buf, sizeof(buf), "JDWP %s", buf); 669 } 670 if (env != NULL) { 671 (*((*env)->FatalError))(env, buf); 672 } else { 673 /* Should rarely ever reach here, means VM is really dead */ 674 print_message(stderr, "ERROR: JDWP: ", "\n", 675 "Can't call JNI FatalError(NULL, \"%s\")", buf); 676 } 677 forceExit(exit_code); 678 } 679 680 /* 681 * Initialize debugger back end modules 682 */ 683 static void 684 initialize(JNIEnv *env, jthread thread, EventIndex triggering_ei) 685 { 686 jvmtiError error; 687 EnumerateArg arg; 688 jbyte suspendPolicy; 689 690 LOG_MISC(("Begin initialize()")); 691 currentSessionID = 0; 692 initComplete = JNI_FALSE; 693 694 if ( gdata->vmDead ) { 695 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at initialize() time"); 696 } 697 698 /* Turn off the initial JVMTI event notifications */ 699 error = set_event_notification(JVMTI_DISABLE, EI_EXCEPTION); 700 if (error != JVMTI_ERROR_NONE) { 701 EXIT_ERROR(error, "unable to disable JVMTI event notification"); 702 } 703 error = set_event_notification(JVMTI_DISABLE, EI_VM_INIT); 704 if (error != JVMTI_ERROR_NONE) { 705 EXIT_ERROR(error, "unable to disable JVMTI event notification"); 706 } 707 error = set_event_notification(JVMTI_DISABLE, EI_VM_DEATH); 708 if (error != JVMTI_ERROR_NONE) { 709 EXIT_ERROR(error, "unable to disable JVMTI event notification"); 710 } 711 712 /* Remove initial event callbacks */ 713 (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks)); 714 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks) 715 (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks)); 716 if (error != JVMTI_ERROR_NONE) { 717 EXIT_ERROR(error, "unable to clear JVMTI callbacks"); 718 } 719 720 commonRef_initialize(); 721 util_initialize(env); 722 threadControl_initialize(); 723 stepControl_initialize(); 724 invoker_initialize(); 725 debugDispatch_initialize(); 726 classTrack_initialize(env); 727 debugLoop_initialize(); 728 729 initMonitor = debugMonitorCreate("JDWP Initialization Monitor"); 730 731 732 /* 733 * Initialize transports 734 */ 735 arg.isServer = isServer; 736 arg.error = JDWP_ERROR(NONE); 737 arg.startCount = 0; 738 739 transport_initialize(); 740 (void)bagEnumerateOver(transports, startTransport, &arg); 741 742 /* 743 * Exit with an error only if 744 * 1) none of the transports was successfully started, and 745 * 2) the application has not yet started running 746 */ 747 if ((arg.error != JDWP_ERROR(NONE)) && 748 (arg.startCount == 0) && 749 initOnStartup) { 750 EXIT_ERROR(map2jvmtiError(arg.error), "No transports initialized"); 751 } 752 753 eventHandler_initialize(currentSessionID); 754 755 signalInitComplete(); 756 757 transport_waitForConnection(); 758 759 suspendPolicy = suspendOnInit ? JDWP_SUSPEND_POLICY(ALL) 760 : JDWP_SUSPEND_POLICY(NONE); 761 if (triggering_ei == EI_VM_INIT) { 762 LOG_MISC(("triggering_ei == EI_VM_INIT")); 763 eventHelper_reportVMInit(env, currentSessionID, thread, suspendPolicy); 764 } else { 765 /* 766 * TO DO: Kludgy way of getting the triggering event to the 767 * just-attached debugger. It would be nice to make this a little 768 * cleaner. There is also a race condition where other events 769 * can get in the queue (from other not-yet-suspended threads) 770 * before this one does. (Also need to handle allocation error below?) 771 */ 772 EventInfo info; 773 struct bag *initEventBag; 774 LOG_MISC(("triggering_ei != EI_VM_INIT")); 775 initEventBag = eventHelper_createEventBag(); 776 (void)memset(&info,0,sizeof(info)); 777 info.ei = triggering_ei; 778 eventHelper_recordEvent(&info, 0, suspendPolicy, initEventBag); 779 (void)eventHelper_reportEvents(currentSessionID, initEventBag); 780 bagDestroyBag(initEventBag); 781 } 782 783 if ( gdata->vmDead ) { 784 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead before initialize() completes"); 785 } 786 LOG_MISC(("End initialize()")); 787 } 788 789 /* 790 * Restore all static data to the initialized state so that another 791 * debugger can connect properly later. 792 */ 793 void 794 debugInit_reset(JNIEnv *env) 795 { 796 EnumerateArg arg; 797 798 LOG_MISC(("debugInit_reset() beginning")); 799 800 currentSessionID++; 801 initComplete = JNI_FALSE; 802 803 eventHandler_reset(currentSessionID); 804 transport_reset(); 805 debugDispatch_reset(); 806 invoker_reset(); 807 stepControl_reset(); 808 threadControl_reset(); 809 util_reset(); 810 commonRef_reset(env); 811 classTrack_reset(); 812 813 /* 814 * If this is a server, we are now ready to accept another connection. 815 * If it's a client, then we've cleaned up some (more should be added 816 * later) and we're done. 817 */ 818 if (isServer) { 819 arg.isServer = JNI_TRUE; 820 arg.error = JDWP_ERROR(NONE); 821 arg.startCount = 0; 822 (void)bagEnumerateOver(transports, startTransport, &arg); 823 824 signalInitComplete(); 825 826 transport_waitForConnection(); 827 } else { 828 signalInitComplete(); /* Why? */ 829 } 830 831 LOG_MISC(("debugInit_reset() completed.")); 832 } 833 834 835 char * 836 debugInit_launchOnInit(void) 837 { 838 return launchOnInit; 839 } 840 841 jboolean 842 debugInit_suspendOnInit(void) 843 { 844 return suspendOnInit; 845 } 846 847 /* 848 * code below is shamelessly swiped from hprof. 849 */ 850 851 static int 852 get_tok(char **src, char *buf, int buflen, char sep) 853 { 854 int i; 855 char *p = *src; 856 for (i = 0; i < buflen; i++) { 857 if (p[i] == 0 || p[i] == sep) { 858 buf[i] = 0; 859 if (p[i] == sep) { 860 i++; 861 } 862 *src += i; 863 return i; 864 } 865 buf[i] = p[i]; 866 } 867 /* overflow */ 868 return 0; 869 } 870 871 static void 872 printUsage(void) 873 { 874 TTY_MESSAGE(( 875 " Java Debugger JDWP Agent Library\n" 876 " --------------------------------\n" 877 "\n" 878 " (see http://java.sun.com/products/jpda for more information)\n" 879 "\n" 880 "jdwp usage: java " AGENTLIB "=[help]|[<option>=<value>, ...]\n" 881 "\n" 882 "Option Name and Value Description Default\n" 883 "--------------------- ----------- -------\n" 884 "suspend=y|n wait on startup? y\n" 885 "transport=<name> transport spec none\n" 886 "address=<listen/attach address> transport spec \"\"\n" 887 "server=y|n listen for debugger? n\n" 888 "launch=<command line> run debugger on event none\n" 889 "onthrow=<exception name> debug on throw none\n" 890 "onuncaught=y|n debug on any uncaught? n\n" 891 "timeout=<timeout value> for listen/attach in milliseconds n\n" 892 "mutf8=y|n output modified utf-8 n\n" 893 "quiet=y|n control over terminal messages n\n" 894 "\n" 895 "Obsolete Options\n" 896 "----------------\n" 897 "strict=y|n\n" 898 "stdalloc=y|n\n" 899 "\n" 900 "Examples\n" 901 "--------\n" 902 " - Using sockets connect to a debugger at a specific address:\n" 903 " java " AGENTLIB "=transport=dt_socket,address=localhost:8000 ...\n" 904 " - Using sockets listen for a debugger to attach:\n" 905 " java " AGENTLIB "=transport=dt_socket,server=y,suspend=y ...\n" 906 "\n" 907 "Notes\n" 908 "-----\n" 909 " - A timeout value of 0 (the default) is no timeout.\n" 910 "\n" 911 "Warnings\n" 912 "--------\n" 913 " - The older " XRUN " interface can still be used, but will be removed in\n" 914 " a future release, for example:\n" 915 " java " XDEBUG " " XRUN ":[help]|[<option>=<value>, ...]\n" 916 )); 917 918 #ifdef DEBUG 919 920 TTY_MESSAGE(( 921 "\n" 922 "Debugging Options Description Default\n" 923 "----------------- ----------- -------\n" 924 "pause=y|n pause to debug PID n\n" 925 "coredump=y|n coredump at exit n\n" 926 "errorexit=y|n exit on any error n\n" 927 "logfile=filename name of log file none\n" 928 "logflags=flags log flags (bitmask) none\n" 929 " JVM calls = 0x001\n" 930 " JNI calls = 0x002\n" 931 " JVMTI calls = 0x004\n" 932 " misc events = 0x008\n" 933 " step logs = 0x010\n" 934 " locations = 0x020\n" 935 " callbacks = 0x040\n" 936 " errors = 0x080\n" 937 " everything = 0xfff\n" 938 "debugflags=flags debug flags (bitmask) none\n" 939 " USE_ITERATE_THROUGH_HEAP 0x01\n" 940 "\n" 941 "Environment Variables\n" 942 "---------------------\n" 943 "_JAVA_JDWP_OPTIONS\n" 944 " Options can be added externally via this environment variable.\n" 945 " Anything contained in it will get a comma prepended to it (if needed),\n" 946 " then it will be added to the end of the options supplied via the\n" 947 " " XRUN " or " AGENTLIB " command line option.\n" 948 )); 949 950 #endif 951 952 953 954 } 955 956 static jboolean checkAddress(void *bagItem, void *arg) 957 { 958 TransportSpec *spec = (TransportSpec *)bagItem; 959 if (spec->address == NULL) { 960 ERROR_MESSAGE(("JDWP Non-server transport %s must have a connection " 961 "address specified through the 'address=' option", 962 spec->name)); 963 return JNI_FALSE; 964 } else { 965 return JNI_TRUE; 966 } 967 } 968 969 static char * 970 add_to_options(char *options, char *new_options) 971 { 972 size_t originalLength; 973 char *combinedOptions; 974 975 /* 976 * Allocate enough space for both strings and 977 * comma in between. 978 */ 979 originalLength = strlen(options); 980 combinedOptions = jvmtiAllocate((jint)originalLength + 1 + 981 (jint)strlen(new_options) + 1); 982 if (combinedOptions == NULL) { 983 return NULL; 984 } 985 986 (void)strcpy(combinedOptions, options); 987 (void)strcat(combinedOptions, ","); 988 (void)strcat(combinedOptions, new_options); 989 990 return combinedOptions; 991 } 992 993 static jboolean 994 get_boolean(char **pstr, jboolean *answer) 995 { 996 char buf[80]; 997 *answer = JNI_FALSE; 998 /*LINTED*/ 999 if (get_tok(pstr, buf, (int)sizeof(buf), ',')) { 1000 if (strcmp(buf, "y") == 0) { 1001 *answer = JNI_TRUE; 1002 return JNI_TRUE; 1003 } else if (strcmp(buf, "n") == 0) { 1004 *answer = JNI_FALSE; 1005 return JNI_TRUE; 1006 } 1007 } 1008 return JNI_FALSE; 1009 } 1010 1011 /* atexit() callback */ 1012 static void 1013 atexit_finish_logging(void) 1014 { 1015 /* Normal exit(0) (not _exit()) may only reach here */ 1016 finish_logging(0); /* Only first call matters */ 1017 } 1018 1019 static jboolean 1020 parseOptions(char *options) 1021 { 1022 TransportSpec *currentTransport = NULL; 1023 char *end; 1024 char *current; 1025 int length; 1026 char *str; 1027 char *errmsg; 1028 1029 /* Set defaults */ 1030 gdata->assertOn = DEFAULT_ASSERT_ON; 1031 gdata->assertFatal = DEFAULT_ASSERT_FATAL; 1032 logfile = DEFAULT_LOGFILE; 1033 1034 /* Options being NULL will end up being an error. */ 1035 if (options == NULL) { 1036 options = ""; 1037 } 1038 1039 /* Check for "help" BEFORE we add any environmental settings */ 1040 if ((strcmp(options, "help")) == 0) { 1041 printUsage(); 1042 forceExit(0); /* Kill entire process, no core dump wanted */ 1043 } 1044 1045 /* These buffers are never freed */ 1046 { 1047 char *envOptions; 1048 1049 /* 1050 * Add environmentally specified options. 1051 */ 1052 envOptions = getenv("_JAVA_JDWP_OPTIONS"); 1053 if (envOptions != NULL) { 1054 options = add_to_options(options, envOptions); 1055 if ( options==NULL ) { 1056 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options"); 1057 } 1058 } 1059 1060 /* 1061 * Allocate a buffer for names derived from option strings. It should 1062 * never be longer than the original options string itself. 1063 * Also keep a copy of the options in gdata->options. 1064 */ 1065 length = (int)strlen(options); 1066 gdata->options = jvmtiAllocate(length + 1); 1067 if (gdata->options == NULL) { 1068 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options"); 1069 } 1070 (void)strcpy(gdata->options, options); 1071 names = jvmtiAllocate(length + 1); 1072 if (names == NULL) { 1073 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options"); 1074 } 1075 1076 transports = bagCreateBag(sizeof(TransportSpec), 3); 1077 if (transports == NULL) { 1078 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"transports"); 1079 } 1080 1081 } 1082 1083 current = names; 1084 end = names + length; 1085 str = options; 1086 1087 while (*str) { 1088 char buf[100]; 1089 /*LINTED*/ 1090 if (!get_tok(&str, buf, (int)sizeof(buf), '=')) { 1091 goto syntax_error; 1092 } 1093 if (strcmp(buf, "transport") == 0) { 1094 currentTransport = bagAdd(transports); 1095 /*LINTED*/ 1096 if (!get_tok(&str, current, (int)(end - current), ',')) { 1097 goto syntax_error; 1098 } 1099 currentTransport->name = current; 1100 current += strlen(current) + 1; 1101 } else if (strcmp(buf, "address") == 0) { 1102 if (currentTransport == NULL) { 1103 errmsg = "address specified without transport"; 1104 goto bad_option_with_errmsg; 1105 } 1106 /*LINTED*/ 1107 if (!get_tok(&str, current, (int)(end - current), ',')) { 1108 goto syntax_error; 1109 } 1110 currentTransport->address = current; 1111 current += strlen(current) + 1; 1112 } else if (strcmp(buf, "timeout") == 0) { 1113 if (currentTransport == NULL) { 1114 errmsg = "timeout specified without transport"; 1115 goto bad_option_with_errmsg; 1116 } 1117 /*LINTED*/ 1118 if (!get_tok(&str, current, (int)(end - current), ',')) { 1119 goto syntax_error; 1120 } 1121 currentTransport->timeout = atol(current); 1122 current += strlen(current) + 1; 1123 } else if (strcmp(buf, "launch") == 0) { 1124 /*LINTED*/ 1125 if (!get_tok(&str, current, (int)(end - current), ',')) { 1126 goto syntax_error; 1127 } 1128 launchOnInit = current; 1129 current += strlen(current) + 1; 1130 } else if (strcmp(buf, "onthrow") == 0) { 1131 /* Read class name and convert in place to a signature */ 1132 *current = 'L'; 1133 /*LINTED*/ 1134 if (!get_tok(&str, current + 1, (int)(end - current - 1), ',')) { 1135 goto syntax_error; 1136 } 1137 initOnException = current; 1138 while (*current != '\0') { 1139 if (*current == '.') { 1140 *current = '/'; 1141 } 1142 current++; 1143 } 1144 *current++ = ';'; 1145 *current++ = '\0'; 1146 } else if (strcmp(buf, "assert") == 0) { 1147 /*LINTED*/ 1148 if (!get_tok(&str, current, (int)(end - current), ',')) { 1149 goto syntax_error; 1150 } 1151 if (strcmp(current, "y") == 0) { 1152 gdata->assertOn = JNI_TRUE; 1153 gdata->assertFatal = JNI_FALSE; 1154 } else if (strcmp(current, "fatal") == 0) { 1155 gdata->assertOn = JNI_TRUE; 1156 gdata->assertFatal = JNI_TRUE; 1157 } else if (strcmp(current, "n") == 0) { 1158 gdata->assertOn = JNI_FALSE; 1159 gdata->assertFatal = JNI_FALSE; 1160 } else { 1161 goto syntax_error; 1162 } 1163 current += strlen(current) + 1; 1164 } else if (strcmp(buf, "pause") == 0) { 1165 if ( !get_boolean(&str, &dopause) ) { 1166 goto syntax_error; 1167 } 1168 if ( dopause ) { 1169 do_pause(); 1170 } 1171 } else if (strcmp(buf, "coredump") == 0) { 1172 if ( !get_boolean(&str, &docoredump) ) { 1173 goto syntax_error; 1174 } 1175 } else if (strcmp(buf, "errorexit") == 0) { 1176 if ( !get_boolean(&str, &(gdata->doerrorexit)) ) { 1177 goto syntax_error; 1178 } 1179 } else if (strcmp(buf, "exitpause") == 0) { 1180 errmsg = "The exitpause option removed, use -XX:OnError"; 1181 goto bad_option_with_errmsg; 1182 } else if (strcmp(buf, "precrash") == 0) { 1183 errmsg = "The precrash option removed, use -XX:OnError"; 1184 goto bad_option_with_errmsg; 1185 } else if (strcmp(buf, "logfile") == 0) { 1186 /*LINTED*/ 1187 if (!get_tok(&str, current, (int)(end - current), ',')) { 1188 goto syntax_error; 1189 } 1190 logfile = current; 1191 current += strlen(current) + 1; 1192 } else if (strcmp(buf, "logflags") == 0) { 1193 /*LINTED*/ 1194 if (!get_tok(&str, current, (int)(end - current), ',')) { 1195 goto syntax_error; 1196 } 1197 /*LINTED*/ 1198 logflags = (unsigned)strtol(current, NULL, 0); 1199 } else if (strcmp(buf, "debugflags") == 0) { 1200 /*LINTED*/ 1201 if (!get_tok(&str, current, (int)(end - current), ',')) { 1202 goto syntax_error; 1203 } 1204 /*LINTED*/ 1205 gdata->debugflags = (unsigned)strtol(current, NULL, 0); 1206 } else if ( strcmp(buf, "suspend")==0 ) { 1207 if ( !get_boolean(&str, &suspendOnInit) ) { 1208 goto syntax_error; 1209 } 1210 } else if ( strcmp(buf, "server")==0 ) { 1211 if ( !get_boolean(&str, &isServer) ) { 1212 goto syntax_error; 1213 } 1214 } else if ( strcmp(buf, "strict")==0 ) { /* Obsolete, but accept it */ 1215 if ( !get_boolean(&str, &isStrict) ) { 1216 goto syntax_error; 1217 } 1218 } else if ( strcmp(buf, "quiet")==0 ) { 1219 if ( !get_boolean(&str, &(gdata->quiet)) ) { 1220 goto syntax_error; 1221 } 1222 } else if ( strcmp(buf, "onuncaught")==0 ) { 1223 if ( !get_boolean(&str, &initOnUncaught) ) { 1224 goto syntax_error; 1225 } 1226 } else if ( strcmp(buf, "mutf8")==0 ) { 1227 if ( !get_boolean(&str, &(gdata->modifiedUtf8)) ) { 1228 goto syntax_error; 1229 } 1230 } else if ( strcmp(buf, "stdalloc")==0 ) { /* Obsolete, but accept it */ 1231 if ( !get_boolean(&str, &useStandardAlloc) ) { 1232 goto syntax_error; 1233 } 1234 } else { 1235 goto syntax_error; 1236 } 1237 } 1238 1239 /* Setup logging now */ 1240 if ( logfile!=NULL ) { 1241 setup_logging(logfile, logflags); 1242 (void)atexit(&atexit_finish_logging); 1243 } 1244 1245 if (bagSize(transports) == 0) { 1246 errmsg = "no transport specified"; 1247 goto bad_option_with_errmsg; 1248 } 1249 1250 /* 1251 * TO DO: Remove when multiple transports are allowed. (replace with 1252 * check below. 1253 */ 1254 if (bagSize(transports) > 1) { 1255 errmsg = "multiple transports are not supported in this release"; 1256 goto bad_option_with_errmsg; 1257 } 1258 1259 1260 if (!isServer) { 1261 jboolean specified = bagEnumerateOver(transports, checkAddress, NULL); 1262 if (!specified) { 1263 /* message already printed */ 1264 goto bad_option_no_msg; 1265 } 1266 } 1267 1268 /* 1269 * The user has selected to wait for an exception before init happens 1270 */ 1271 if ((initOnException != NULL) || (initOnUncaught)) { 1272 initOnStartup = JNI_FALSE; 1273 1274 if (launchOnInit == NULL) { 1275 /* 1276 * These rely on the launch=/usr/bin/foo 1277 * suboption, so it is an error if user did not 1278 * provide one. 1279 */ 1280 errmsg = "Specify launch=<command line> when using onthrow or onuncaught suboption"; 1281 goto bad_option_with_errmsg; 1282 } 1283 } 1284 1285 return JNI_TRUE; 1286 1287 syntax_error: 1288 ERROR_MESSAGE(("JDWP option syntax error: %s=%s", AGENTLIB, options)); 1289 return JNI_FALSE; 1290 1291 bad_option_with_errmsg: 1292 ERROR_MESSAGE(("JDWP %s: %s=%s", errmsg, AGENTLIB, options)); 1293 return JNI_FALSE; 1294 1295 bad_option_no_msg: 1296 ERROR_MESSAGE(("JDWP %s: %s=%s", "invalid option", AGENTLIB, options)); 1297 return JNI_FALSE; 1298 } 1299 1300 /* All normal exit doors lead here */ 1301 void 1302 debugInit_exit(jvmtiError error, const char *msg) 1303 { 1304 int exit_code = 0; 1305 1306 /* Pick an error code */ 1307 if ( error != JVMTI_ERROR_NONE ) { 1308 exit_code = 1; 1309 if ( docoredump ) { 1310 finish_logging(exit_code); 1311 abort(); 1312 } 1313 } 1314 if ( msg==NULL ) { 1315 msg = ""; 1316 } 1317 1318 LOG_MISC(("Exiting with error %s(%d): %s", jvmtiErrorText(error), error, msg)); 1319 1320 gdata->vmDead = JNI_TRUE; 1321 1322 /* Let's try and cleanup the JVMTI, if we even have one */ 1323 if ( gdata->jvmti != NULL ) { 1324 /* Dispose of jvmti (gdata->jvmti becomes NULL) */ 1325 disposeEnvironment(gdata->jvmti); 1326 } 1327 1328 /* Finish up logging. We reach here if JDWP is doing the exiting. */ 1329 finish_logging(exit_code); /* Only first call matters */ 1330 1331 /* Let's give the JNI a FatalError if non-exit 0, which is historic way */ 1332 if ( exit_code != 0 ) { 1333 JNIEnv *env = NULL; 1334 jniFatalError(env, msg, error, exit_code); 1335 } 1336 1337 /* Last chance to die, this kills the entire process. */ 1338 forceExit(exit_code); 1339 }