Tue, 11 May 2010 14:35:43 -0700
6931180: Migration to recent versions of MS Platform SDK
6951582: Build problems on win64
Summary: Changes to enable building JDK7 with Microsoft Visual Studio 2010
Reviewed-by: ohair, art, ccheung, dcubed
duke@435 | 1 | /* |
twisti@1819 | 2 | * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
duke@435 | 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@435 | 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@435 | 21 | * have any questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
duke@435 | 25 | # include "incls/_precompiled.incl" |
duke@435 | 26 | # include "incls/_vmError.cpp.incl" |
duke@435 | 27 | |
duke@435 | 28 | // List of environment variables that should be reported in error log file. |
duke@435 | 29 | const char *env_list[] = { |
duke@435 | 30 | // All platforms |
duke@435 | 31 | "JAVA_HOME", "JRE_HOME", "JAVA_TOOL_OPTIONS", "_JAVA_OPTIONS", "CLASSPATH", |
duke@435 | 32 | "JAVA_COMPILER", "PATH", "USERNAME", |
duke@435 | 33 | |
duke@435 | 34 | // Env variables that are defined on Solaris/Linux |
duke@435 | 35 | "LD_LIBRARY_PATH", "LD_PRELOAD", "SHELL", "DISPLAY", |
duke@435 | 36 | "HOSTTYPE", "OSTYPE", "ARCH", "MACHTYPE", |
duke@435 | 37 | |
duke@435 | 38 | // defined on Linux |
duke@435 | 39 | "LD_ASSUME_KERNEL", "_JAVA_SR_SIGNUM", |
duke@435 | 40 | |
duke@435 | 41 | // defined on Windows |
duke@435 | 42 | "OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR", |
duke@435 | 43 | |
duke@435 | 44 | (const char *)0 |
duke@435 | 45 | }; |
duke@435 | 46 | |
duke@435 | 47 | // Fatal error handler for internal errors and crashes. |
duke@435 | 48 | // |
duke@435 | 49 | // The default behavior of fatal error handler is to print a brief message |
duke@435 | 50 | // to standard out (defaultStream::output_fd()), then save detailed information |
duke@435 | 51 | // into an error report file (hs_err_pid<pid>.log) and abort VM. If multiple |
duke@435 | 52 | // threads are having troubles at the same time, only one error is reported. |
duke@435 | 53 | // The thread that is reporting error will abort VM when it is done, all other |
duke@435 | 54 | // threads are blocked forever inside report_and_die(). |
duke@435 | 55 | |
duke@435 | 56 | // Constructor for crashes |
duke@435 | 57 | VMError::VMError(Thread* thread, int sig, address pc, void* siginfo, void* context) { |
duke@435 | 58 | _thread = thread; |
duke@435 | 59 | _id = sig; |
duke@435 | 60 | _pc = pc; |
duke@435 | 61 | _siginfo = siginfo; |
duke@435 | 62 | _context = context; |
duke@435 | 63 | |
duke@435 | 64 | _verbose = false; |
duke@435 | 65 | _current_step = 0; |
duke@435 | 66 | _current_step_info = NULL; |
duke@435 | 67 | |
duke@435 | 68 | _message = ""; |
duke@435 | 69 | _filename = NULL; |
duke@435 | 70 | _lineno = 0; |
duke@435 | 71 | |
duke@435 | 72 | _size = 0; |
duke@435 | 73 | } |
duke@435 | 74 | |
duke@435 | 75 | // Constructor for internal errors |
duke@435 | 76 | VMError::VMError(Thread* thread, const char* message, const char* filename, int lineno) { |
duke@435 | 77 | _thread = thread; |
duke@435 | 78 | _id = internal_error; // set it to a value that's not an OS exception/signal |
duke@435 | 79 | _filename = filename; |
duke@435 | 80 | _lineno = lineno; |
duke@435 | 81 | _message = message; |
duke@435 | 82 | |
duke@435 | 83 | _verbose = false; |
duke@435 | 84 | _current_step = 0; |
duke@435 | 85 | _current_step_info = NULL; |
duke@435 | 86 | |
duke@435 | 87 | _pc = NULL; |
duke@435 | 88 | _siginfo = NULL; |
duke@435 | 89 | _context = NULL; |
duke@435 | 90 | |
duke@435 | 91 | _size = 0; |
duke@435 | 92 | } |
duke@435 | 93 | |
duke@435 | 94 | // Constructor for OOM errors |
duke@435 | 95 | VMError::VMError(Thread* thread, size_t size, const char* message, const char* filename, int lineno) { |
duke@435 | 96 | _thread = thread; |
duke@435 | 97 | _id = oom_error; // set it to a value that's not an OS exception/signal |
duke@435 | 98 | _filename = filename; |
duke@435 | 99 | _lineno = lineno; |
duke@435 | 100 | _message = message; |
duke@435 | 101 | |
duke@435 | 102 | _verbose = false; |
duke@435 | 103 | _current_step = 0; |
duke@435 | 104 | _current_step_info = NULL; |
duke@435 | 105 | |
duke@435 | 106 | _pc = NULL; |
duke@435 | 107 | _siginfo = NULL; |
duke@435 | 108 | _context = NULL; |
duke@435 | 109 | |
duke@435 | 110 | _size = size; |
duke@435 | 111 | } |
duke@435 | 112 | |
duke@435 | 113 | |
duke@435 | 114 | // Constructor for non-fatal errors |
duke@435 | 115 | VMError::VMError(const char* message) { |
duke@435 | 116 | _thread = NULL; |
duke@435 | 117 | _id = internal_error; // set it to a value that's not an OS exception/signal |
duke@435 | 118 | _filename = NULL; |
duke@435 | 119 | _lineno = 0; |
duke@435 | 120 | _message = message; |
duke@435 | 121 | |
duke@435 | 122 | _verbose = false; |
duke@435 | 123 | _current_step = 0; |
duke@435 | 124 | _current_step_info = NULL; |
duke@435 | 125 | |
duke@435 | 126 | _pc = NULL; |
duke@435 | 127 | _siginfo = NULL; |
duke@435 | 128 | _context = NULL; |
duke@435 | 129 | |
duke@435 | 130 | _size = 0; |
duke@435 | 131 | } |
duke@435 | 132 | |
duke@435 | 133 | // -XX:OnError=<string>, where <string> can be a list of commands, separated |
duke@435 | 134 | // by ';'. "%p" is replaced by current process id (pid); "%%" is replaced by |
duke@435 | 135 | // a single "%". Some examples: |
duke@435 | 136 | // |
duke@435 | 137 | // -XX:OnError="pmap %p" // show memory map |
duke@435 | 138 | // -XX:OnError="gcore %p; dbx - %p" // dump core and launch debugger |
duke@435 | 139 | // -XX:OnError="cat hs_err_pid%p.log | mail my_email@sun.com" |
duke@435 | 140 | // -XX:OnError="kill -9 %p" // ?#!@# |
duke@435 | 141 | |
duke@435 | 142 | // A simple parser for -XX:OnError, usage: |
duke@435 | 143 | // ptr = OnError; |
duke@435 | 144 | // while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr) != NULL) |
duke@435 | 145 | // ... ... |
duke@435 | 146 | static char* next_OnError_command(char* buf, int buflen, const char** ptr) { |
duke@435 | 147 | if (ptr == NULL || *ptr == NULL) return NULL; |
duke@435 | 148 | |
duke@435 | 149 | const char* cmd = *ptr; |
duke@435 | 150 | |
duke@435 | 151 | // skip leading blanks or ';' |
duke@435 | 152 | while (*cmd == ' ' || *cmd == ';') cmd++; |
duke@435 | 153 | |
duke@435 | 154 | if (*cmd == '\0') return NULL; |
duke@435 | 155 | |
duke@435 | 156 | const char * cmdend = cmd; |
duke@435 | 157 | while (*cmdend != '\0' && *cmdend != ';') cmdend++; |
duke@435 | 158 | |
duke@435 | 159 | Arguments::copy_expand_pid(cmd, cmdend - cmd, buf, buflen); |
duke@435 | 160 | |
duke@435 | 161 | *ptr = (*cmdend == '\0' ? cmdend : cmdend + 1); |
duke@435 | 162 | return buf; |
duke@435 | 163 | } |
duke@435 | 164 | |
duke@435 | 165 | |
duke@435 | 166 | static void print_bug_submit_message(outputStream *out, Thread *thread) { |
duke@435 | 167 | if (out == NULL) return; |
duke@435 | 168 | out->print_raw_cr("# If you would like to submit a bug report, please visit:"); |
duke@435 | 169 | out->print_raw ("# "); |
duke@435 | 170 | out->print_raw_cr(Arguments::java_vendor_url_bug()); |
duke@435 | 171 | // If the crash is in native code, encourage user to submit a bug to the |
duke@435 | 172 | // provider of that code. |
coleenp@491 | 173 | if (thread && thread->is_Java_thread() && |
coleenp@491 | 174 | !thread->is_hidden_from_external_view()) { |
duke@435 | 175 | JavaThread* jt = (JavaThread*)thread; |
duke@435 | 176 | if (jt->thread_state() == _thread_in_native) { |
duke@435 | 177 | out->print_cr("# The crash happened outside the Java Virtual Machine in native code.\n# See problematic frame for where to report the bug."); |
duke@435 | 178 | } |
duke@435 | 179 | } |
duke@435 | 180 | out->print_raw_cr("#"); |
duke@435 | 181 | } |
duke@435 | 182 | |
duke@435 | 183 | |
duke@435 | 184 | // Return a string to describe the error |
duke@435 | 185 | char* VMError::error_string(char* buf, int buflen) { |
duke@435 | 186 | char signame_buf[64]; |
duke@435 | 187 | const char *signame = os::exception_name(_id, signame_buf, sizeof(signame_buf)); |
duke@435 | 188 | |
duke@435 | 189 | if (signame) { |
duke@435 | 190 | jio_snprintf(buf, buflen, |
duke@435 | 191 | "%s (0x%x) at pc=" PTR_FORMAT ", pid=%d, tid=" UINTX_FORMAT, |
duke@435 | 192 | signame, _id, _pc, |
duke@435 | 193 | os::current_process_id(), os::current_thread_id()); |
duke@435 | 194 | } else { |
duke@435 | 195 | if (_filename != NULL && _lineno > 0) { |
duke@435 | 196 | // skip directory names |
duke@435 | 197 | char separator = os::file_separator()[0]; |
duke@435 | 198 | const char *p = strrchr(_filename, separator); |
duke@435 | 199 | |
duke@435 | 200 | jio_snprintf(buf, buflen, |
duke@435 | 201 | "Internal Error at %s:%d, pid=%d, tid=" UINTX_FORMAT " \nError: %s", |
duke@435 | 202 | p ? p + 1 : _filename, _lineno, |
duke@435 | 203 | os::current_process_id(), os::current_thread_id(), |
duke@435 | 204 | _message ? _message : ""); |
duke@435 | 205 | } else { |
duke@435 | 206 | jio_snprintf(buf, buflen, |
duke@435 | 207 | "Internal Error (0x%x), pid=%d, tid=" UINTX_FORMAT, |
duke@435 | 208 | _id, os::current_process_id(), os::current_thread_id()); |
duke@435 | 209 | } |
duke@435 | 210 | } |
duke@435 | 211 | |
duke@435 | 212 | return buf; |
duke@435 | 213 | } |
duke@435 | 214 | |
twisti@1819 | 215 | void VMError::print_stack_trace(outputStream* st, JavaThread* jt, |
twisti@1819 | 216 | char* buf, int buflen, bool verbose) { |
twisti@1819 | 217 | #ifdef ZERO |
twisti@1819 | 218 | if (jt->zero_stack()->sp() && jt->top_zero_frame()) { |
twisti@1819 | 219 | // StackFrameStream uses the frame anchor, which may not have |
twisti@1819 | 220 | // been set up. This can be done at any time in Zero, however, |
twisti@1819 | 221 | // so if it hasn't been set up then we just set it up now and |
twisti@1819 | 222 | // clear it again when we're done. |
twisti@1819 | 223 | bool has_last_Java_frame = jt->has_last_Java_frame(); |
twisti@1819 | 224 | if (!has_last_Java_frame) |
twisti@1819 | 225 | jt->set_last_Java_frame(); |
twisti@1819 | 226 | st->print("Java frames:"); |
twisti@1819 | 227 | |
twisti@1819 | 228 | // If the top frame is a Shark frame and the frame anchor isn't |
twisti@1819 | 229 | // set up then it's possible that the information in the frame |
twisti@1819 | 230 | // is garbage: it could be from a previous decache, or it could |
twisti@1819 | 231 | // simply have never been written. So we print a warning... |
twisti@1819 | 232 | StackFrameStream sfs(jt); |
twisti@1819 | 233 | if (!has_last_Java_frame && !sfs.is_done()) { |
twisti@1819 | 234 | if (sfs.current()->zeroframe()->is_shark_frame()) { |
twisti@1819 | 235 | st->print(" (TOP FRAME MAY BE JUNK)"); |
twisti@1819 | 236 | } |
twisti@1819 | 237 | } |
twisti@1819 | 238 | st->cr(); |
twisti@1819 | 239 | |
twisti@1819 | 240 | // Print the frames |
twisti@1819 | 241 | for(int i = 0; !sfs.is_done(); sfs.next(), i++) { |
twisti@1819 | 242 | sfs.current()->zero_print_on_error(i, st, buf, buflen); |
twisti@1819 | 243 | st->cr(); |
twisti@1819 | 244 | } |
twisti@1819 | 245 | |
twisti@1819 | 246 | // Reset the frame anchor if necessary |
twisti@1819 | 247 | if (!has_last_Java_frame) |
twisti@1819 | 248 | jt->reset_last_Java_frame(); |
twisti@1819 | 249 | } |
twisti@1819 | 250 | #else |
twisti@1819 | 251 | if (jt->has_last_Java_frame()) { |
twisti@1819 | 252 | st->print_cr("Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)"); |
twisti@1819 | 253 | for(StackFrameStream sfs(jt); !sfs.is_done(); sfs.next()) { |
twisti@1819 | 254 | sfs.current()->print_on_error(st, buf, buflen, verbose); |
twisti@1819 | 255 | st->cr(); |
twisti@1819 | 256 | } |
twisti@1819 | 257 | } |
twisti@1819 | 258 | #endif // ZERO |
twisti@1819 | 259 | } |
duke@435 | 260 | |
duke@435 | 261 | // This is the main function to report a fatal error. Only one thread can |
duke@435 | 262 | // call this function, so we don't need to worry about MT-safety. But it's |
duke@435 | 263 | // possible that the error handler itself may crash or die on an internal |
duke@435 | 264 | // error, for example, when the stack/heap is badly damaged. We must be |
duke@435 | 265 | // able to handle recursive errors that happen inside error handler. |
duke@435 | 266 | // |
duke@435 | 267 | // Error reporting is done in several steps. If a crash or internal error |
duke@435 | 268 | // occurred when reporting an error, the nested signal/exception handler |
duke@435 | 269 | // can skip steps that are already (or partially) done. Error reporting will |
duke@435 | 270 | // continue from the next step. This allows us to retrieve and print |
duke@435 | 271 | // information that may be unsafe to get after a fatal error. If it happens, |
duke@435 | 272 | // you may find nested report_and_die() frames when you look at the stack |
duke@435 | 273 | // in a debugger. |
duke@435 | 274 | // |
duke@435 | 275 | // In general, a hang in error handler is much worse than a crash or internal |
duke@435 | 276 | // error, as it's harder to recover from a hang. Deadlock can happen if we |
duke@435 | 277 | // try to grab a lock that is already owned by current thread, or if the |
duke@435 | 278 | // owner is blocked forever (e.g. in os::infinite_sleep()). If possible, the |
duke@435 | 279 | // error handler and all the functions it called should avoid grabbing any |
duke@435 | 280 | // lock. An important thing to notice is that memory allocation needs a lock. |
duke@435 | 281 | // |
duke@435 | 282 | // We should avoid using large stack allocated buffers. Many errors happen |
duke@435 | 283 | // when stack space is already low. Making things even worse is that there |
duke@435 | 284 | // could be nested report_and_die() calls on stack (see above). Only one |
duke@435 | 285 | // thread can report error, so large buffers are statically allocated in data |
duke@435 | 286 | // segment. |
duke@435 | 287 | |
duke@435 | 288 | void VMError::report(outputStream* st) { |
duke@435 | 289 | # define BEGIN if (_current_step == 0) { _current_step = 1; |
duke@435 | 290 | # define STEP(n, s) } if (_current_step < n) { _current_step = n; _current_step_info = s; |
duke@435 | 291 | # define END } |
duke@435 | 292 | |
duke@435 | 293 | // don't allocate large buffer on stack |
duke@435 | 294 | static char buf[O_BUFLEN]; |
duke@435 | 295 | |
duke@435 | 296 | BEGIN |
duke@435 | 297 | |
coleenp@491 | 298 | STEP(10, "(printing fatal error message)") |
duke@435 | 299 | |
duke@435 | 300 | st->print_cr("#"); |
coleenp@491 | 301 | st->print_cr("# A fatal error has been detected by the Java Runtime Environment:"); |
duke@435 | 302 | |
duke@435 | 303 | STEP(15, "(printing type of error)") |
duke@435 | 304 | |
duke@435 | 305 | switch(_id) { |
duke@435 | 306 | case oom_error: |
duke@435 | 307 | st->print_cr("#"); |
duke@435 | 308 | st->print("# java.lang.OutOfMemoryError: "); |
duke@435 | 309 | if (_size) { |
duke@435 | 310 | st->print("requested "); |
kvn@855 | 311 | sprintf(buf,SIZE_FORMAT,_size); |
duke@435 | 312 | st->print(buf); |
duke@435 | 313 | st->print(" bytes"); |
duke@435 | 314 | if (_message != NULL) { |
duke@435 | 315 | st->print(" for "); |
duke@435 | 316 | st->print(_message); |
duke@435 | 317 | } |
duke@435 | 318 | st->print_cr(". Out of swap space?"); |
duke@435 | 319 | } else { |
duke@435 | 320 | if (_message != NULL) |
duke@435 | 321 | st->print_cr(_message); |
duke@435 | 322 | } |
duke@435 | 323 | break; |
duke@435 | 324 | case internal_error: |
duke@435 | 325 | default: |
duke@435 | 326 | break; |
duke@435 | 327 | } |
duke@435 | 328 | |
duke@435 | 329 | STEP(20, "(printing exception/signal name)") |
duke@435 | 330 | |
duke@435 | 331 | st->print_cr("#"); |
duke@435 | 332 | st->print("# "); |
duke@435 | 333 | // Is it an OS exception/signal? |
duke@435 | 334 | if (os::exception_name(_id, buf, sizeof(buf))) { |
duke@435 | 335 | st->print("%s", buf); |
duke@435 | 336 | st->print(" (0x%x)", _id); // signal number |
duke@435 | 337 | st->print(" at pc=" PTR_FORMAT, _pc); |
duke@435 | 338 | } else { |
duke@435 | 339 | st->print("Internal Error"); |
duke@435 | 340 | if (_filename != NULL && _lineno > 0) { |
duke@435 | 341 | #ifdef PRODUCT |
duke@435 | 342 | // In product mode chop off pathname? |
duke@435 | 343 | char separator = os::file_separator()[0]; |
duke@435 | 344 | const char *p = strrchr(_filename, separator); |
duke@435 | 345 | const char *file = p ? p+1 : _filename; |
duke@435 | 346 | #else |
duke@435 | 347 | const char *file = _filename; |
duke@435 | 348 | #endif |
duke@435 | 349 | size_t len = strlen(file); |
duke@435 | 350 | size_t buflen = sizeof(buf); |
duke@435 | 351 | |
duke@435 | 352 | strncpy(buf, file, buflen); |
duke@435 | 353 | if (len + 10 < buflen) { |
twisti@1038 | 354 | sprintf(buf + len, ":%d", _lineno); |
duke@435 | 355 | } |
duke@435 | 356 | st->print(" (%s)", buf); |
duke@435 | 357 | } else { |
duke@435 | 358 | st->print(" (0x%x)", _id); |
duke@435 | 359 | } |
duke@435 | 360 | } |
duke@435 | 361 | |
duke@435 | 362 | STEP(30, "(printing current thread and pid)") |
duke@435 | 363 | |
duke@435 | 364 | // process id, thread id |
duke@435 | 365 | st->print(", pid=%d", os::current_process_id()); |
duke@435 | 366 | st->print(", tid=" UINTX_FORMAT, os::current_thread_id()); |
duke@435 | 367 | st->cr(); |
duke@435 | 368 | |
duke@435 | 369 | STEP(40, "(printing error message)") |
duke@435 | 370 | |
duke@435 | 371 | // error message |
duke@435 | 372 | if (_message && _message[0] != '\0') { |
duke@435 | 373 | st->print_cr("# Error: %s", _message); |
duke@435 | 374 | } |
duke@435 | 375 | |
duke@435 | 376 | STEP(50, "(printing Java version string)") |
duke@435 | 377 | |
duke@435 | 378 | // VM version |
duke@435 | 379 | st->print_cr("#"); |
coleenp@908 | 380 | JDK_Version::current().to_string(buf, sizeof(buf)); |
coleenp@908 | 381 | st->print_cr("# JRE version: %s", buf); |
coleenp@548 | 382 | st->print_cr("# Java VM: %s (%s %s %s %s)", |
duke@435 | 383 | Abstract_VM_Version::vm_name(), |
duke@435 | 384 | Abstract_VM_Version::vm_release(), |
duke@435 | 385 | Abstract_VM_Version::vm_info_string(), |
coleenp@548 | 386 | Abstract_VM_Version::vm_platform_string(), |
coleenp@548 | 387 | UseCompressedOops ? "compressed oops" : "" |
duke@435 | 388 | ); |
duke@435 | 389 | |
duke@435 | 390 | STEP(60, "(printing problematic frame)") |
duke@435 | 391 | |
duke@435 | 392 | // Print current frame if we have a context (i.e. it's a crash) |
duke@435 | 393 | if (_context) { |
duke@435 | 394 | st->print_cr("# Problematic frame:"); |
duke@435 | 395 | st->print("# "); |
duke@435 | 396 | frame fr = os::fetch_frame_from_context(_context); |
duke@435 | 397 | fr.print_on_error(st, buf, sizeof(buf)); |
duke@435 | 398 | st->cr(); |
duke@435 | 399 | st->print_cr("#"); |
duke@435 | 400 | } |
duke@435 | 401 | |
duke@435 | 402 | STEP(65, "(printing bug submit message)") |
duke@435 | 403 | |
duke@435 | 404 | if (_verbose) print_bug_submit_message(st, _thread); |
duke@435 | 405 | |
duke@435 | 406 | STEP(70, "(printing thread)" ) |
duke@435 | 407 | |
duke@435 | 408 | if (_verbose) { |
duke@435 | 409 | st->cr(); |
duke@435 | 410 | st->print_cr("--------------- T H R E A D ---------------"); |
duke@435 | 411 | st->cr(); |
duke@435 | 412 | } |
duke@435 | 413 | |
duke@435 | 414 | STEP(80, "(printing current thread)" ) |
duke@435 | 415 | |
duke@435 | 416 | // current thread |
duke@435 | 417 | if (_verbose) { |
duke@435 | 418 | if (_thread) { |
duke@435 | 419 | st->print("Current thread (" PTR_FORMAT "): ", _thread); |
duke@435 | 420 | _thread->print_on_error(st, buf, sizeof(buf)); |
duke@435 | 421 | st->cr(); |
duke@435 | 422 | } else { |
duke@435 | 423 | st->print_cr("Current thread is native thread"); |
duke@435 | 424 | } |
duke@435 | 425 | st->cr(); |
duke@435 | 426 | } |
duke@435 | 427 | |
duke@435 | 428 | STEP(90, "(printing siginfo)" ) |
duke@435 | 429 | |
duke@435 | 430 | // signal no, signal code, address that caused the fault |
duke@435 | 431 | if (_verbose && _siginfo) { |
duke@435 | 432 | os::print_siginfo(st, _siginfo); |
duke@435 | 433 | st->cr(); |
duke@435 | 434 | } |
duke@435 | 435 | |
duke@435 | 436 | STEP(100, "(printing registers, top of stack, instructions near pc)") |
duke@435 | 437 | |
duke@435 | 438 | // registers, top of stack, instructions near pc |
duke@435 | 439 | if (_verbose && _context) { |
duke@435 | 440 | os::print_context(st, _context); |
duke@435 | 441 | st->cr(); |
duke@435 | 442 | } |
duke@435 | 443 | |
duke@435 | 444 | STEP(110, "(printing stack bounds)" ) |
duke@435 | 445 | |
duke@435 | 446 | if (_verbose) { |
duke@435 | 447 | st->print("Stack: "); |
duke@435 | 448 | |
duke@435 | 449 | address stack_top; |
duke@435 | 450 | size_t stack_size; |
duke@435 | 451 | |
duke@435 | 452 | if (_thread) { |
duke@435 | 453 | stack_top = _thread->stack_base(); |
duke@435 | 454 | stack_size = _thread->stack_size(); |
duke@435 | 455 | } else { |
duke@435 | 456 | stack_top = os::current_stack_base(); |
duke@435 | 457 | stack_size = os::current_stack_size(); |
duke@435 | 458 | } |
duke@435 | 459 | |
duke@435 | 460 | address stack_bottom = stack_top - stack_size; |
duke@435 | 461 | st->print("[" PTR_FORMAT "," PTR_FORMAT "]", stack_bottom, stack_top); |
duke@435 | 462 | |
duke@435 | 463 | frame fr = _context ? os::fetch_frame_from_context(_context) |
duke@435 | 464 | : os::current_frame(); |
duke@435 | 465 | |
duke@435 | 466 | if (fr.sp()) { |
duke@435 | 467 | st->print(", sp=" PTR_FORMAT, fr.sp()); |
twisti@1038 | 468 | st->print(", free space=%" INTPTR_FORMAT "k", |
duke@435 | 469 | ((intptr_t)fr.sp() - (intptr_t)stack_bottom) >> 10); |
duke@435 | 470 | } |
duke@435 | 471 | |
duke@435 | 472 | st->cr(); |
duke@435 | 473 | } |
duke@435 | 474 | |
duke@435 | 475 | STEP(120, "(printing native stack)" ) |
duke@435 | 476 | |
duke@435 | 477 | if (_verbose) { |
duke@435 | 478 | frame fr = _context ? os::fetch_frame_from_context(_context) |
duke@435 | 479 | : os::current_frame(); |
duke@435 | 480 | |
duke@435 | 481 | // see if it's a valid frame |
duke@435 | 482 | if (fr.pc()) { |
duke@435 | 483 | st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); |
duke@435 | 484 | |
duke@435 | 485 | int count = 0; |
duke@435 | 486 | |
duke@435 | 487 | while (count++ < StackPrintLimit) { |
duke@435 | 488 | fr.print_on_error(st, buf, sizeof(buf)); |
duke@435 | 489 | st->cr(); |
duke@435 | 490 | if (os::is_first_C_frame(&fr)) break; |
duke@435 | 491 | fr = os::get_sender_for_C_frame(&fr); |
duke@435 | 492 | } |
duke@435 | 493 | |
duke@435 | 494 | if (count > StackPrintLimit) { |
duke@435 | 495 | st->print_cr("...<more frames>..."); |
duke@435 | 496 | } |
duke@435 | 497 | |
duke@435 | 498 | st->cr(); |
duke@435 | 499 | } |
duke@435 | 500 | } |
duke@435 | 501 | |
duke@435 | 502 | STEP(130, "(printing Java stack)" ) |
duke@435 | 503 | |
duke@435 | 504 | if (_verbose && _thread && _thread->is_Java_thread()) { |
twisti@1819 | 505 | print_stack_trace(st, (JavaThread*)_thread, buf, sizeof(buf)); |
duke@435 | 506 | } |
duke@435 | 507 | |
minqi@1554 | 508 | STEP(135, "(printing target Java thread stack)" ) |
minqi@1554 | 509 | |
minqi@1554 | 510 | // printing Java thread stack trace if it is involved in GC crash |
minqi@1554 | 511 | if (_verbose && (_thread->is_Named_thread())) { |
minqi@1554 | 512 | JavaThread* jt = ((NamedThread *)_thread)->processed_thread(); |
minqi@1554 | 513 | if (jt != NULL) { |
minqi@1554 | 514 | st->print_cr("JavaThread " PTR_FORMAT " (nid = " UINTX_FORMAT ") was being processed", jt, jt->osthread()->thread_id()); |
twisti@1819 | 515 | print_stack_trace(st, jt, buf, sizeof(buf), true); |
minqi@1554 | 516 | } |
minqi@1554 | 517 | } |
minqi@1554 | 518 | |
duke@435 | 519 | STEP(140, "(printing VM operation)" ) |
duke@435 | 520 | |
duke@435 | 521 | if (_verbose && _thread && _thread->is_VM_thread()) { |
duke@435 | 522 | VMThread* t = (VMThread*)_thread; |
duke@435 | 523 | VM_Operation* op = t->vm_operation(); |
duke@435 | 524 | if (op) { |
duke@435 | 525 | op->print_on_error(st); |
duke@435 | 526 | st->cr(); |
duke@435 | 527 | st->cr(); |
duke@435 | 528 | } |
duke@435 | 529 | } |
duke@435 | 530 | |
duke@435 | 531 | STEP(150, "(printing current compile task)" ) |
duke@435 | 532 | |
duke@435 | 533 | if (_verbose && _thread && _thread->is_Compiler_thread()) { |
duke@435 | 534 | CompilerThread* t = (CompilerThread*)_thread; |
duke@435 | 535 | if (t->task()) { |
duke@435 | 536 | st->cr(); |
duke@435 | 537 | st->print_cr("Current CompileTask:"); |
duke@435 | 538 | t->task()->print_line_on_error(st, buf, sizeof(buf)); |
duke@435 | 539 | st->cr(); |
duke@435 | 540 | } |
duke@435 | 541 | } |
duke@435 | 542 | |
duke@435 | 543 | STEP(160, "(printing process)" ) |
duke@435 | 544 | |
duke@435 | 545 | if (_verbose) { |
duke@435 | 546 | st->cr(); |
duke@435 | 547 | st->print_cr("--------------- P R O C E S S ---------------"); |
duke@435 | 548 | st->cr(); |
duke@435 | 549 | } |
duke@435 | 550 | |
duke@435 | 551 | STEP(170, "(printing all threads)" ) |
duke@435 | 552 | |
duke@435 | 553 | // all threads |
duke@435 | 554 | if (_verbose && _thread) { |
duke@435 | 555 | Threads::print_on_error(st, _thread, buf, sizeof(buf)); |
duke@435 | 556 | st->cr(); |
duke@435 | 557 | } |
duke@435 | 558 | |
duke@435 | 559 | STEP(175, "(printing VM state)" ) |
duke@435 | 560 | |
duke@435 | 561 | if (_verbose) { |
duke@435 | 562 | // Safepoint state |
duke@435 | 563 | st->print("VM state:"); |
duke@435 | 564 | |
duke@435 | 565 | if (SafepointSynchronize::is_synchronizing()) st->print("synchronizing"); |
duke@435 | 566 | else if (SafepointSynchronize::is_at_safepoint()) st->print("at safepoint"); |
duke@435 | 567 | else st->print("not at safepoint"); |
duke@435 | 568 | |
duke@435 | 569 | // Also see if error occurred during initialization or shutdown |
duke@435 | 570 | if (!Universe::is_fully_initialized()) { |
duke@435 | 571 | st->print(" (not fully initialized)"); |
duke@435 | 572 | } else if (VM_Exit::vm_exited()) { |
duke@435 | 573 | st->print(" (shutting down)"); |
duke@435 | 574 | } else { |
duke@435 | 575 | st->print(" (normal execution)"); |
duke@435 | 576 | } |
duke@435 | 577 | st->cr(); |
duke@435 | 578 | st->cr(); |
duke@435 | 579 | } |
duke@435 | 580 | |
duke@435 | 581 | STEP(180, "(printing owned locks on error)" ) |
duke@435 | 582 | |
duke@435 | 583 | // mutexes/monitors that currently have an owner |
duke@435 | 584 | if (_verbose) { |
duke@435 | 585 | print_owned_locks_on_error(st); |
duke@435 | 586 | st->cr(); |
duke@435 | 587 | } |
duke@435 | 588 | |
duke@435 | 589 | STEP(190, "(printing heap information)" ) |
duke@435 | 590 | |
duke@435 | 591 | if (_verbose && Universe::is_fully_initialized()) { |
duke@435 | 592 | // print heap information before vm abort |
duke@435 | 593 | Universe::print_on(st); |
duke@435 | 594 | st->cr(); |
duke@435 | 595 | } |
duke@435 | 596 | |
duke@435 | 597 | STEP(200, "(printing dynamic libraries)" ) |
duke@435 | 598 | |
duke@435 | 599 | if (_verbose) { |
duke@435 | 600 | // dynamic libraries, or memory map |
duke@435 | 601 | os::print_dll_info(st); |
duke@435 | 602 | st->cr(); |
duke@435 | 603 | } |
duke@435 | 604 | |
duke@435 | 605 | STEP(210, "(printing VM options)" ) |
duke@435 | 606 | |
duke@435 | 607 | if (_verbose) { |
duke@435 | 608 | // VM options |
duke@435 | 609 | Arguments::print_on(st); |
duke@435 | 610 | st->cr(); |
duke@435 | 611 | } |
duke@435 | 612 | |
duke@435 | 613 | STEP(220, "(printing environment variables)" ) |
duke@435 | 614 | |
duke@435 | 615 | if (_verbose) { |
duke@435 | 616 | os::print_environment_variables(st, env_list, buf, sizeof(buf)); |
duke@435 | 617 | st->cr(); |
duke@435 | 618 | } |
duke@435 | 619 | |
duke@435 | 620 | STEP(225, "(printing signal handlers)" ) |
duke@435 | 621 | |
duke@435 | 622 | if (_verbose) { |
duke@435 | 623 | os::print_signal_handlers(st, buf, sizeof(buf)); |
duke@435 | 624 | st->cr(); |
duke@435 | 625 | } |
duke@435 | 626 | |
duke@435 | 627 | STEP(230, "" ) |
duke@435 | 628 | |
duke@435 | 629 | if (_verbose) { |
duke@435 | 630 | st->cr(); |
duke@435 | 631 | st->print_cr("--------------- S Y S T E M ---------------"); |
duke@435 | 632 | st->cr(); |
duke@435 | 633 | } |
duke@435 | 634 | |
duke@435 | 635 | STEP(240, "(printing OS information)" ) |
duke@435 | 636 | |
duke@435 | 637 | if (_verbose) { |
duke@435 | 638 | os::print_os_info(st); |
duke@435 | 639 | st->cr(); |
duke@435 | 640 | } |
duke@435 | 641 | |
duke@435 | 642 | STEP(250, "(printing CPU info)" ) |
duke@435 | 643 | if (_verbose) { |
duke@435 | 644 | os::print_cpu_info(st); |
duke@435 | 645 | st->cr(); |
duke@435 | 646 | } |
duke@435 | 647 | |
duke@435 | 648 | STEP(260, "(printing memory info)" ) |
duke@435 | 649 | |
duke@435 | 650 | if (_verbose) { |
duke@435 | 651 | os::print_memory_info(st); |
duke@435 | 652 | st->cr(); |
duke@435 | 653 | } |
duke@435 | 654 | |
duke@435 | 655 | STEP(270, "(printing internal vm info)" ) |
duke@435 | 656 | |
duke@435 | 657 | if (_verbose) { |
duke@435 | 658 | st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string()); |
duke@435 | 659 | st->cr(); |
duke@435 | 660 | } |
duke@435 | 661 | |
duke@435 | 662 | STEP(280, "(printing date and time)" ) |
duke@435 | 663 | |
duke@435 | 664 | if (_verbose) { |
duke@435 | 665 | os::print_date_and_time(st); |
duke@435 | 666 | st->cr(); |
duke@435 | 667 | } |
duke@435 | 668 | |
duke@435 | 669 | END |
duke@435 | 670 | |
duke@435 | 671 | # undef BEGIN |
duke@435 | 672 | # undef STEP |
duke@435 | 673 | # undef END |
duke@435 | 674 | } |
duke@435 | 675 | |
duke@435 | 676 | |
duke@435 | 677 | void VMError::report_and_die() { |
duke@435 | 678 | // Don't allocate large buffer on stack |
duke@435 | 679 | static char buffer[O_BUFLEN]; |
duke@435 | 680 | |
duke@435 | 681 | // First error, and its thread id. We must be able to handle native thread, |
duke@435 | 682 | // so use thread id instead of Thread* to identify thread. |
duke@435 | 683 | static VMError* first_error; |
duke@435 | 684 | static jlong first_error_tid; |
duke@435 | 685 | |
duke@435 | 686 | // An error could happen before tty is initialized or after it has been |
duke@435 | 687 | // destroyed. Here we use a very simple unbuffered fdStream for printing. |
duke@435 | 688 | // Only out.print_raw() and out.print_raw_cr() should be used, as other |
duke@435 | 689 | // printing methods need to allocate large buffer on stack. To format a |
duke@435 | 690 | // string, use jio_snprintf() with a static buffer or use staticBufferStream. |
duke@435 | 691 | static fdStream out(defaultStream::output_fd()); |
duke@435 | 692 | |
duke@435 | 693 | // How many errors occurred in error handler when reporting first_error. |
duke@435 | 694 | static int recursive_error_count; |
duke@435 | 695 | |
duke@435 | 696 | // We will first print a brief message to standard out (verbose = false), |
duke@435 | 697 | // then save detailed information in log file (verbose = true). |
duke@435 | 698 | static bool out_done = false; // done printing to standard out |
duke@435 | 699 | static bool log_done = false; // done saving error log |
duke@435 | 700 | static fdStream log; // error log |
duke@435 | 701 | |
duke@435 | 702 | if (SuppressFatalErrorMessage) { |
duke@435 | 703 | os::abort(); |
duke@435 | 704 | } |
duke@435 | 705 | jlong mytid = os::current_thread_id(); |
duke@435 | 706 | if (first_error == NULL && |
duke@435 | 707 | Atomic::cmpxchg_ptr(this, &first_error, NULL) == NULL) { |
duke@435 | 708 | |
duke@435 | 709 | // first time |
duke@435 | 710 | first_error_tid = mytid; |
duke@435 | 711 | set_error_reported(); |
duke@435 | 712 | |
duke@435 | 713 | if (ShowMessageBoxOnError) { |
duke@435 | 714 | show_message_box(buffer, sizeof(buffer)); |
duke@435 | 715 | |
duke@435 | 716 | // User has asked JVM to abort. Reset ShowMessageBoxOnError so the |
duke@435 | 717 | // WatcherThread can kill JVM if the error handler hangs. |
duke@435 | 718 | ShowMessageBoxOnError = false; |
duke@435 | 719 | } |
duke@435 | 720 | |
duke@435 | 721 | // reset signal handlers or exception filter; make sure recursive crashes |
duke@435 | 722 | // are handled properly. |
duke@435 | 723 | reset_signal_handlers(); |
duke@435 | 724 | |
duke@435 | 725 | } else { |
coleenp@946 | 726 | // If UseOsErrorReporting we call this for each level of the call stack |
coleenp@946 | 727 | // while searching for the exception handler. Only the first level needs |
coleenp@946 | 728 | // to be reported. |
coleenp@946 | 729 | if (UseOSErrorReporting && log_done) return; |
coleenp@946 | 730 | |
duke@435 | 731 | // This is not the first error, see if it happened in a different thread |
duke@435 | 732 | // or in the same thread during error reporting. |
duke@435 | 733 | if (first_error_tid != mytid) { |
duke@435 | 734 | jio_snprintf(buffer, sizeof(buffer), |
duke@435 | 735 | "[thread " INT64_FORMAT " also had an error]", |
duke@435 | 736 | mytid); |
duke@435 | 737 | out.print_raw_cr(buffer); |
duke@435 | 738 | |
duke@435 | 739 | // error reporting is not MT-safe, block current thread |
duke@435 | 740 | os::infinite_sleep(); |
duke@435 | 741 | |
duke@435 | 742 | } else { |
duke@435 | 743 | if (recursive_error_count++ > 30) { |
duke@435 | 744 | out.print_raw_cr("[Too many errors, abort]"); |
duke@435 | 745 | os::die(); |
duke@435 | 746 | } |
duke@435 | 747 | |
duke@435 | 748 | jio_snprintf(buffer, sizeof(buffer), |
duke@435 | 749 | "[error occurred during error reporting %s, id 0x%x]", |
duke@435 | 750 | first_error ? first_error->_current_step_info : "", |
duke@435 | 751 | _id); |
duke@435 | 752 | if (log.is_open()) { |
duke@435 | 753 | log.cr(); |
duke@435 | 754 | log.print_raw_cr(buffer); |
duke@435 | 755 | log.cr(); |
duke@435 | 756 | } else { |
duke@435 | 757 | out.cr(); |
duke@435 | 758 | out.print_raw_cr(buffer); |
duke@435 | 759 | out.cr(); |
duke@435 | 760 | } |
duke@435 | 761 | } |
duke@435 | 762 | } |
duke@435 | 763 | |
duke@435 | 764 | // print to screen |
duke@435 | 765 | if (!out_done) { |
duke@435 | 766 | first_error->_verbose = false; |
duke@435 | 767 | |
duke@435 | 768 | staticBufferStream sbs(buffer, sizeof(buffer), &out); |
duke@435 | 769 | first_error->report(&sbs); |
duke@435 | 770 | |
duke@435 | 771 | out_done = true; |
duke@435 | 772 | |
duke@435 | 773 | first_error->_current_step = 0; // reset current_step |
duke@435 | 774 | first_error->_current_step_info = ""; // reset current_step string |
duke@435 | 775 | } |
duke@435 | 776 | |
duke@435 | 777 | // print to error log file |
duke@435 | 778 | if (!log_done) { |
duke@435 | 779 | first_error->_verbose = true; |
duke@435 | 780 | |
duke@435 | 781 | // see if log file is already open |
duke@435 | 782 | if (!log.is_open()) { |
duke@435 | 783 | // open log file |
duke@435 | 784 | int fd = -1; |
duke@435 | 785 | |
duke@435 | 786 | if (ErrorFile != NULL) { |
duke@435 | 787 | bool copy_ok = |
duke@435 | 788 | Arguments::copy_expand_pid(ErrorFile, strlen(ErrorFile), buffer, sizeof(buffer)); |
duke@435 | 789 | if (copy_ok) { |
duke@435 | 790 | fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666); |
duke@435 | 791 | } |
duke@435 | 792 | } |
duke@435 | 793 | |
duke@435 | 794 | if (fd == -1) { |
duke@435 | 795 | const char *cwd = os::get_current_directory(buffer, sizeof(buffer)); |
duke@435 | 796 | size_t len = strlen(cwd); |
duke@435 | 797 | // either user didn't specify, or the user's location failed, |
duke@435 | 798 | // so use the default name in the current directory |
duke@435 | 799 | jio_snprintf(&buffer[len], sizeof(buffer)-len, "%shs_err_pid%u.log", |
duke@435 | 800 | os::file_separator(), os::current_process_id()); |
duke@435 | 801 | fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666); |
duke@435 | 802 | } |
duke@435 | 803 | |
duke@435 | 804 | if (fd == -1) { |
duke@435 | 805 | // try temp directory |
duke@435 | 806 | const char * tmpdir = os::get_temp_directory(); |
coleenp@1788 | 807 | jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log", |
coleenp@1788 | 808 | tmpdir, os::file_separator(), os::current_process_id()); |
duke@435 | 809 | fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666); |
duke@435 | 810 | } |
duke@435 | 811 | |
duke@435 | 812 | if (fd != -1) { |
duke@435 | 813 | out.print_raw("# An error report file with more information is saved as:\n# "); |
duke@435 | 814 | out.print_raw_cr(buffer); |
duke@435 | 815 | os::set_error_file(buffer); |
duke@435 | 816 | |
duke@435 | 817 | log.set_fd(fd); |
duke@435 | 818 | } else { |
duke@435 | 819 | out.print_raw_cr("# Can not save log file, dump to screen.."); |
duke@435 | 820 | log.set_fd(defaultStream::output_fd()); |
duke@435 | 821 | } |
duke@435 | 822 | } |
duke@435 | 823 | |
duke@435 | 824 | staticBufferStream sbs(buffer, O_BUFLEN, &log); |
duke@435 | 825 | first_error->report(&sbs); |
duke@435 | 826 | first_error->_current_step = 0; // reset current_step |
duke@435 | 827 | first_error->_current_step_info = ""; // reset current_step string |
duke@435 | 828 | |
duke@435 | 829 | if (log.fd() != defaultStream::output_fd()) { |
duke@435 | 830 | close(log.fd()); |
duke@435 | 831 | } |
duke@435 | 832 | |
duke@435 | 833 | log.set_fd(-1); |
duke@435 | 834 | log_done = true; |
duke@435 | 835 | } |
duke@435 | 836 | |
duke@435 | 837 | |
duke@435 | 838 | static bool skip_OnError = false; |
duke@435 | 839 | if (!skip_OnError && OnError && OnError[0]) { |
duke@435 | 840 | skip_OnError = true; |
duke@435 | 841 | |
duke@435 | 842 | out.print_raw_cr("#"); |
duke@435 | 843 | out.print_raw ("# -XX:OnError=\""); |
duke@435 | 844 | out.print_raw (OnError); |
duke@435 | 845 | out.print_raw_cr("\""); |
duke@435 | 846 | |
duke@435 | 847 | char* cmd; |
duke@435 | 848 | const char* ptr = OnError; |
duke@435 | 849 | while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){ |
duke@435 | 850 | out.print_raw ("# Executing "); |
duke@435 | 851 | #if defined(LINUX) |
duke@435 | 852 | out.print_raw ("/bin/sh -c "); |
duke@435 | 853 | #elif defined(SOLARIS) |
duke@435 | 854 | out.print_raw ("/usr/bin/sh -c "); |
duke@435 | 855 | #endif |
duke@435 | 856 | out.print_raw ("\""); |
duke@435 | 857 | out.print_raw (cmd); |
duke@435 | 858 | out.print_raw_cr("\" ..."); |
duke@435 | 859 | |
duke@435 | 860 | os::fork_and_exec(cmd); |
duke@435 | 861 | } |
duke@435 | 862 | |
duke@435 | 863 | // done with OnError |
duke@435 | 864 | OnError = NULL; |
duke@435 | 865 | } |
duke@435 | 866 | |
duke@435 | 867 | static bool skip_bug_url = false; |
duke@435 | 868 | if (!skip_bug_url) { |
duke@435 | 869 | skip_bug_url = true; |
duke@435 | 870 | |
duke@435 | 871 | out.print_raw_cr("#"); |
duke@435 | 872 | print_bug_submit_message(&out, _thread); |
duke@435 | 873 | } |
duke@435 | 874 | |
duke@435 | 875 | if (!UseOSErrorReporting) { |
duke@435 | 876 | // os::abort() will call abort hooks, try it first. |
duke@435 | 877 | static bool skip_os_abort = false; |
duke@435 | 878 | if (!skip_os_abort) { |
duke@435 | 879 | skip_os_abort = true; |
duke@435 | 880 | os::abort(); |
duke@435 | 881 | } |
duke@435 | 882 | |
duke@435 | 883 | // if os::abort() doesn't abort, try os::die(); |
duke@435 | 884 | os::die(); |
duke@435 | 885 | } |
duke@435 | 886 | } |
duke@435 | 887 | |
duke@435 | 888 | /* |
duke@435 | 889 | * OnOutOfMemoryError scripts/commands executed while VM is a safepoint - this |
duke@435 | 890 | * ensures utilities such as jmap can observe the process is a consistent state. |
duke@435 | 891 | */ |
duke@435 | 892 | class VM_ReportJavaOutOfMemory : public VM_Operation { |
duke@435 | 893 | private: |
duke@435 | 894 | VMError *_err; |
duke@435 | 895 | public: |
duke@435 | 896 | VM_ReportJavaOutOfMemory(VMError *err) { _err = err; } |
duke@435 | 897 | VMOp_Type type() const { return VMOp_ReportJavaOutOfMemory; } |
duke@435 | 898 | void doit(); |
duke@435 | 899 | }; |
duke@435 | 900 | |
duke@435 | 901 | void VM_ReportJavaOutOfMemory::doit() { |
duke@435 | 902 | // Don't allocate large buffer on stack |
duke@435 | 903 | static char buffer[O_BUFLEN]; |
duke@435 | 904 | |
duke@435 | 905 | tty->print_cr("#"); |
duke@435 | 906 | tty->print_cr("# java.lang.OutOfMemoryError: %s", _err->message()); |
duke@435 | 907 | tty->print_cr("# -XX:OnOutOfMemoryError=\"%s\"", OnOutOfMemoryError); |
duke@435 | 908 | |
duke@435 | 909 | // make heap parsability |
duke@435 | 910 | Universe::heap()->ensure_parsability(false); // no need to retire TLABs |
duke@435 | 911 | |
duke@435 | 912 | char* cmd; |
duke@435 | 913 | const char* ptr = OnOutOfMemoryError; |
duke@435 | 914 | while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){ |
duke@435 | 915 | tty->print("# Executing "); |
duke@435 | 916 | #if defined(LINUX) |
duke@435 | 917 | tty->print ("/bin/sh -c "); |
duke@435 | 918 | #elif defined(SOLARIS) |
duke@435 | 919 | tty->print ("/usr/bin/sh -c "); |
duke@435 | 920 | #endif |
duke@435 | 921 | tty->print_cr("\"%s\"...", cmd); |
duke@435 | 922 | |
duke@435 | 923 | os::fork_and_exec(cmd); |
duke@435 | 924 | } |
duke@435 | 925 | } |
duke@435 | 926 | |
duke@435 | 927 | void VMError::report_java_out_of_memory() { |
duke@435 | 928 | if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { |
duke@435 | 929 | MutexLocker ml(Heap_lock); |
duke@435 | 930 | VM_ReportJavaOutOfMemory op(this); |
duke@435 | 931 | VMThread::execute(&op); |
duke@435 | 932 | } |
duke@435 | 933 | } |