--- old/src/os/linux/vm/os_linux.cpp 2011-02-25 15:52:27.138226900 +0100 +++ new/src/os/linux/vm/os_linux.cpp 2011-02-25 15:52:26.709202400 +0100 @@ -2213,7 +2213,7 @@ if (rp == NULL) return; - if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Typical value for buf is // "/jre/lib///libjvm.so". If "/jre/lib/" appears at // the right place in the string, then assume we are installed in a JDK and --- old/src/os/posix/vm/os_posix.cpp 2011-02-25 15:52:33.704602500 +0100 +++ new/src/os/posix/vm/os_posix.cpp 2011-02-25 15:52:33.274577900 +0100 @@ -59,3 +59,12 @@ VMError::report_coredump_status(buffer, success); } +bool os::is_debugger_present() { + // not implemented + return false; +} + +void os::check_for_debugger_and_wait(void) { + // don't do anything on posix platforms + return; +} --- old/src/os/solaris/vm/os_solaris.cpp 2011-02-25 15:52:39.444327300 +0100 +++ new/src/os/solaris/vm/os_solaris.cpp 2011-02-25 15:52:39.026906900 +0100 @@ -2507,7 +2507,7 @@ assert(ret != 0, "cannot locate libjvm"); realpath((char *)dlinfo.dli_fname, buf); - if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Typical value for buf is // "/jre/lib///libjvm.so". If "/jre/lib/" appears at // the right place in the string, then assume we are installed in a JDK and --- old/src/os/windows/vm/os_windows.cpp 2011-02-25 15:52:46.256716900 +0100 +++ new/src/os/windows/vm/os_windows.cpp 2011-02-25 15:52:45.814691700 +0100 @@ -1788,7 +1788,7 @@ } buf[0] = '\0'; - if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Check for an // JAVA_HOME environment variable // and fix up the path so it looks like @@ -3418,6 +3418,20 @@ } +bool os::is_debugger_attached() { + return IsDebuggerPresent() ? true : false; +} + + +void os::check_for_debugger_and_wait(void) { + // if running in a debugger on windows, we want to pause before the console is closed + if (PauseAtExit && os::is_debugger_attached()) { + fprintf(stderr, "Press any key to continue...\n"); + fgetc(stdin); + } +} + + int os::message_box(const char* title, const char* message) { int result = MessageBox(NULL, message, title, MB_YESNO | MB_ICONERROR | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY); --- old/src/share/vm/runtime/arguments.cpp 2011-02-25 15:52:52.768089400 +0100 +++ new/src/share/vm/runtime/arguments.cpp 2011-02-25 15:52:52.348065400 +0100 @@ -78,6 +78,7 @@ const char* Arguments::_java_vendor_url_bug = DEFAULT_VENDOR_URL_BUG; const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER; int Arguments::_sun_java_launcher_pid = -1; +bool Arguments::_created_by_gamma_launcher = false; // These parameters are reset in method parse_vm_init_args(JavaVMInitArgs*) bool Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods; @@ -1656,6 +1657,10 @@ void Arguments::process_java_launcher_argument(const char* launcher, void* extra_info) { _sun_java_launcher = strdup(launcher); + if (strcmp("gamma", _sun_java_launcher) == 0) { + _created_by_gamma_launcher = true; + FLAG_SET_DEFAULT(PauseAtExit, true); + } } bool Arguments::created_by_java_launcher() { @@ -1663,6 +1668,10 @@ return strcmp(DEFAULT_JAVA_LAUNCHER, _sun_java_launcher) != 0; } +bool Arguments::created_by_gamma_launcher() { + return _created_by_gamma_launcher; +} + //=========================================================================================================== // Parsing of main arguments --- old/src/share/vm/runtime/arguments.hpp 2011-02-25 15:52:59.199457200 +0100 +++ new/src/share/vm/runtime/arguments.hpp 2011-02-25 15:52:58.789433800 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -257,6 +257,9 @@ // sun.java.launcher.pid, private property static int _sun_java_launcher_pid; + // was this VM created by the gamma launcher + static bool _created_by_gamma_launcher; + // Option flags static bool _has_profile; static bool _has_alloc_profile; @@ -444,6 +447,8 @@ static const char* sun_java_launcher() { return _sun_java_launcher; } // Was VM created by a Java launcher? static bool created_by_java_launcher(); + // Was VM created by the gamma Java launcher? + static bool created_by_gamma_launcher(); // -Dsun.java.launcher.pid static int sun_java_launcher_pid() { return _sun_java_launcher_pid; } --- old/src/share/vm/runtime/globals.hpp 2011-02-25 15:53:05.192196500 +0100 +++ new/src/share/vm/runtime/globals.hpp 2011-02-25 15:53:04.766172200 +0100 @@ -3749,6 +3749,9 @@ "The file to create and for whose removal to await when pausing " \ "at startup. (default: ./vm.paused.)") \ \ + diagnostic(bool, PauseAtExit, false, \ + "Pause and wait for keypress on exit if a debugger is attached") \ + \ product(bool, ExtendedDTraceProbes, false, \ "Enable performance-impacting dtrace probes") \ \ --- old/src/share/vm/runtime/java.cpp 2011-02-25 15:53:12.079590500 +0100 +++ new/src/share/vm/runtime/java.cpp 2011-02-25 15:53:11.654566200 +0100 @@ -551,6 +551,7 @@ void vm_direct_exit(int code) { notify_vm_shutdown(); + os::check_for_debugger_and_wait(); ::exit(code); } @@ -577,11 +578,13 @@ void vm_shutdown() { vm_perform_shutdown_actions(); + os::check_for_debugger_and_wait(); os::shutdown(); } void vm_abort(bool dump_core) { vm_perform_shutdown_actions(); + os::check_for_debugger_and_wait(); os::abort(dump_core); ShouldNotReachHere(); } --- old/src/share/vm/runtime/os.hpp 2011-02-25 15:53:17.867714600 +0100 +++ new/src/share/vm/runtime/os.hpp 2011-02-25 15:53:17.450690800 +0100 @@ -492,6 +492,12 @@ static void print_location(outputStream* st, intptr_t x, bool verbose = false); static size_t lasterror(char *buf, size_t len); + // Determines whether the calling process is being debugged by a user-mode debugger. + static bool is_debugger_attached(); + + // check if a debugger is attached and if so, wait for a key press + static void os::check_for_debugger_and_wait(void); + // The following two functions are used by fatal error handler to trace // native (C) frames. They are not part of frame.hpp/frame.cpp because // frame.hpp/cpp assume thread is JavaThread, and also because different --- old/src/share/vm/runtime/thread.cpp 2011-02-25 15:53:23.778052700 +0100 +++ new/src/share/vm/runtime/thread.cpp 2011-02-25 15:53:23.341027700 +0100 @@ -3644,6 +3644,7 @@ if (ShowMessageBoxOnError && is_error_reported()) { os::infinite_sleep(); } + os::check_for_debugger_and_wait(); if (JDK_Version::is_jdk12x_version()) { // We are the last thread running, so check if finalizers should be run. --- old/src/share/vm/utilities/vmError.cpp 2011-02-25 15:53:30.273820700 +0100 +++ new/src/share/vm/utilities/vmError.cpp 2011-02-25 15:53:29.886798600 +0100 @@ -802,7 +802,9 @@ first_error_tid = mytid; set_error_reported(); - if (ShowMessageBoxOnError) { + if (ShowMessageBoxOnError || + (PauseAtExit && os::is_debugger_attached())) + { show_message_box(buffer, sizeof(buffer)); // User has asked JVM to abort. Reset ShowMessageBoxOnError so the