Wed, 27 Aug 2014 08:19:12 -0400
8046598: Scalable Native memory tracking development
Summary: Enhance scalability of native memory tracking
Reviewed-by: coleenp, ctornqvi, gtriantafill
duke@435 | 1 | /* |
drchase@6680 | 2 | * Copyright (c) 2003, 2014, Oracle and/or its affiliates. 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 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
stefank@2314 | 25 | #include "precompiled.hpp" |
stefank@2314 | 26 | #include "compiler/compileBroker.hpp" |
stefank@2314 | 27 | #include "gc_interface/collectedHeap.hpp" |
mgerdin@3619 | 28 | #include "prims/whitebox.hpp" |
stefank@2314 | 29 | #include "runtime/arguments.hpp" |
stefank@2314 | 30 | #include "runtime/frame.inline.hpp" |
stefank@2314 | 31 | #include "runtime/init.hpp" |
stefank@2314 | 32 | #include "runtime/os.hpp" |
goetz@6911 | 33 | #include "runtime/thread.inline.hpp" |
stefank@2314 | 34 | #include "runtime/vmThread.hpp" |
stefank@2314 | 35 | #include "runtime/vm_operations.hpp" |
zgu@3900 | 36 | #include "services/memTracker.hpp" |
stefank@2314 | 37 | #include "utilities/debug.hpp" |
zgu@2364 | 38 | #include "utilities/decoder.hpp" |
stefank@2314 | 39 | #include "utilities/defaultStream.hpp" |
kamg@2515 | 40 | #include "utilities/errorReporter.hpp" |
never@3499 | 41 | #include "utilities/events.hpp" |
stefank@2314 | 42 | #include "utilities/top.hpp" |
stefank@2314 | 43 | #include "utilities/vmError.hpp" |
duke@435 | 44 | |
drchase@6680 | 45 | PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC |
drchase@6680 | 46 | |
duke@435 | 47 | // List of environment variables that should be reported in error log file. |
duke@435 | 48 | const char *env_list[] = { |
duke@435 | 49 | // All platforms |
duke@435 | 50 | "JAVA_HOME", "JRE_HOME", "JAVA_TOOL_OPTIONS", "_JAVA_OPTIONS", "CLASSPATH", |
duke@435 | 51 | "JAVA_COMPILER", "PATH", "USERNAME", |
duke@435 | 52 | |
never@3156 | 53 | // Env variables that are defined on Solaris/Linux/BSD |
duke@435 | 54 | "LD_LIBRARY_PATH", "LD_PRELOAD", "SHELL", "DISPLAY", |
duke@435 | 55 | "HOSTTYPE", "OSTYPE", "ARCH", "MACHTYPE", |
duke@435 | 56 | |
duke@435 | 57 | // defined on Linux |
duke@435 | 58 | "LD_ASSUME_KERNEL", "_JAVA_SR_SIGNUM", |
duke@435 | 59 | |
never@3156 | 60 | // defined on Darwin |
never@3156 | 61 | "DYLD_LIBRARY_PATH", "DYLD_FALLBACK_LIBRARY_PATH", |
never@3156 | 62 | "DYLD_FRAMEWORK_PATH", "DYLD_FALLBACK_FRAMEWORK_PATH", |
never@3156 | 63 | "DYLD_INSERT_LIBRARIES", |
never@3156 | 64 | |
duke@435 | 65 | // defined on Windows |
duke@435 | 66 | "OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR", |
duke@435 | 67 | |
duke@435 | 68 | (const char *)0 |
duke@435 | 69 | }; |
duke@435 | 70 | |
duke@435 | 71 | // Fatal error handler for internal errors and crashes. |
duke@435 | 72 | // |
duke@435 | 73 | // The default behavior of fatal error handler is to print a brief message |
duke@435 | 74 | // to standard out (defaultStream::output_fd()), then save detailed information |
duke@435 | 75 | // into an error report file (hs_err_pid<pid>.log) and abort VM. If multiple |
duke@435 | 76 | // threads are having troubles at the same time, only one error is reported. |
duke@435 | 77 | // The thread that is reporting error will abort VM when it is done, all other |
duke@435 | 78 | // threads are blocked forever inside report_and_die(). |
duke@435 | 79 | |
duke@435 | 80 | // Constructor for crashes |
coleenp@2418 | 81 | VMError::VMError(Thread* thread, unsigned int sig, address pc, void* siginfo, void* context) { |
duke@435 | 82 | _thread = thread; |
duke@435 | 83 | _id = sig; |
duke@435 | 84 | _pc = pc; |
duke@435 | 85 | _siginfo = siginfo; |
duke@435 | 86 | _context = context; |
duke@435 | 87 | |
duke@435 | 88 | _verbose = false; |
duke@435 | 89 | _current_step = 0; |
duke@435 | 90 | _current_step_info = NULL; |
duke@435 | 91 | |
jcoomes@1845 | 92 | _message = NULL; |
jcoomes@1845 | 93 | _detail_msg = NULL; |
duke@435 | 94 | _filename = NULL; |
duke@435 | 95 | _lineno = 0; |
duke@435 | 96 | |
duke@435 | 97 | _size = 0; |
duke@435 | 98 | } |
duke@435 | 99 | |
duke@435 | 100 | // Constructor for internal errors |
jcoomes@1845 | 101 | VMError::VMError(Thread* thread, const char* filename, int lineno, |
jcoomes@1845 | 102 | const char* message, const char * detail_msg) |
jcoomes@1845 | 103 | { |
jcoomes@1845 | 104 | _thread = thread; |
ccheung@4993 | 105 | _id = INTERNAL_ERROR; // Value that's not an OS exception/signal |
jcoomes@1845 | 106 | _filename = filename; |
jcoomes@1845 | 107 | _lineno = lineno; |
jcoomes@1845 | 108 | _message = message; |
jcoomes@1845 | 109 | _detail_msg = detail_msg; |
jcoomes@1845 | 110 | |
jcoomes@1845 | 111 | _verbose = false; |
jcoomes@1845 | 112 | _current_step = 0; |
jcoomes@1845 | 113 | _current_step_info = NULL; |
jcoomes@1845 | 114 | |
jcoomes@1845 | 115 | _pc = NULL; |
jcoomes@1845 | 116 | _siginfo = NULL; |
jcoomes@1845 | 117 | _context = NULL; |
jcoomes@1845 | 118 | |
jcoomes@1845 | 119 | _size = 0; |
jcoomes@1845 | 120 | } |
jcoomes@1845 | 121 | |
jcoomes@1845 | 122 | // Constructor for OOM errors |
jcoomes@1845 | 123 | VMError::VMError(Thread* thread, const char* filename, int lineno, size_t size, |
ccheung@4993 | 124 | VMErrorType vm_err_type, const char* message) { |
duke@435 | 125 | _thread = thread; |
ccheung@4993 | 126 | _id = vm_err_type; // Value that's not an OS exception/signal |
duke@435 | 127 | _filename = filename; |
duke@435 | 128 | _lineno = lineno; |
duke@435 | 129 | _message = message; |
jcoomes@1845 | 130 | _detail_msg = NULL; |
duke@435 | 131 | |
duke@435 | 132 | _verbose = false; |
duke@435 | 133 | _current_step = 0; |
duke@435 | 134 | _current_step_info = NULL; |
duke@435 | 135 | |
duke@435 | 136 | _pc = NULL; |
duke@435 | 137 | _siginfo = NULL; |
duke@435 | 138 | _context = NULL; |
duke@435 | 139 | |
duke@435 | 140 | _size = size; |
duke@435 | 141 | } |
duke@435 | 142 | |
duke@435 | 143 | |
duke@435 | 144 | // Constructor for non-fatal errors |
duke@435 | 145 | VMError::VMError(const char* message) { |
duke@435 | 146 | _thread = NULL; |
ccheung@4993 | 147 | _id = INTERNAL_ERROR; // Value that's not an OS exception/signal |
duke@435 | 148 | _filename = NULL; |
duke@435 | 149 | _lineno = 0; |
duke@435 | 150 | _message = message; |
jcoomes@1845 | 151 | _detail_msg = NULL; |
duke@435 | 152 | |
duke@435 | 153 | _verbose = false; |
duke@435 | 154 | _current_step = 0; |
duke@435 | 155 | _current_step_info = NULL; |
duke@435 | 156 | |
duke@435 | 157 | _pc = NULL; |
duke@435 | 158 | _siginfo = NULL; |
duke@435 | 159 | _context = NULL; |
duke@435 | 160 | |
duke@435 | 161 | _size = 0; |
duke@435 | 162 | } |
duke@435 | 163 | |
duke@435 | 164 | // -XX:OnError=<string>, where <string> can be a list of commands, separated |
duke@435 | 165 | // by ';'. "%p" is replaced by current process id (pid); "%%" is replaced by |
duke@435 | 166 | // a single "%". Some examples: |
duke@435 | 167 | // |
duke@435 | 168 | // -XX:OnError="pmap %p" // show memory map |
duke@435 | 169 | // -XX:OnError="gcore %p; dbx - %p" // dump core and launch debugger |
duke@435 | 170 | // -XX:OnError="cat hs_err_pid%p.log | mail my_email@sun.com" |
duke@435 | 171 | // -XX:OnError="kill -9 %p" // ?#!@# |
duke@435 | 172 | |
duke@435 | 173 | // A simple parser for -XX:OnError, usage: |
duke@435 | 174 | // ptr = OnError; |
duke@435 | 175 | // while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr) != NULL) |
duke@435 | 176 | // ... ... |
duke@435 | 177 | static char* next_OnError_command(char* buf, int buflen, const char** ptr) { |
duke@435 | 178 | if (ptr == NULL || *ptr == NULL) return NULL; |
duke@435 | 179 | |
duke@435 | 180 | const char* cmd = *ptr; |
duke@435 | 181 | |
duke@435 | 182 | // skip leading blanks or ';' |
duke@435 | 183 | while (*cmd == ' ' || *cmd == ';') cmd++; |
duke@435 | 184 | |
duke@435 | 185 | if (*cmd == '\0') return NULL; |
duke@435 | 186 | |
duke@435 | 187 | const char * cmdend = cmd; |
duke@435 | 188 | while (*cmdend != '\0' && *cmdend != ';') cmdend++; |
duke@435 | 189 | |
duke@435 | 190 | Arguments::copy_expand_pid(cmd, cmdend - cmd, buf, buflen); |
duke@435 | 191 | |
duke@435 | 192 | *ptr = (*cmdend == '\0' ? cmdend : cmdend + 1); |
duke@435 | 193 | return buf; |
duke@435 | 194 | } |
duke@435 | 195 | |
duke@435 | 196 | |
duke@435 | 197 | static void print_bug_submit_message(outputStream *out, Thread *thread) { |
duke@435 | 198 | if (out == NULL) return; |
duke@435 | 199 | out->print_raw_cr("# If you would like to submit a bug report, please visit:"); |
duke@435 | 200 | out->print_raw ("# "); |
duke@435 | 201 | out->print_raw_cr(Arguments::java_vendor_url_bug()); |
duke@435 | 202 | // If the crash is in native code, encourage user to submit a bug to the |
duke@435 | 203 | // provider of that code. |
coleenp@491 | 204 | if (thread && thread->is_Java_thread() && |
coleenp@491 | 205 | !thread->is_hidden_from_external_view()) { |
duke@435 | 206 | JavaThread* jt = (JavaThread*)thread; |
duke@435 | 207 | if (jt->thread_state() == _thread_in_native) { |
duke@435 | 208 | 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 | 209 | } |
duke@435 | 210 | } |
duke@435 | 211 | out->print_raw_cr("#"); |
duke@435 | 212 | } |
duke@435 | 213 | |
ctornqvi@2520 | 214 | bool VMError::coredump_status; |
ctornqvi@2520 | 215 | char VMError::coredump_message[O_BUFLEN]; |
ctornqvi@2520 | 216 | |
ctornqvi@2520 | 217 | void VMError::report_coredump_status(const char* message, bool status) { |
ctornqvi@2520 | 218 | coredump_status = status; |
ctornqvi@2520 | 219 | strncpy(coredump_message, message, sizeof(coredump_message)); |
ctornqvi@2520 | 220 | coredump_message[sizeof(coredump_message)-1] = 0; |
ctornqvi@2520 | 221 | } |
ctornqvi@2520 | 222 | |
duke@435 | 223 | |
duke@435 | 224 | // Return a string to describe the error |
duke@435 | 225 | char* VMError::error_string(char* buf, int buflen) { |
duke@435 | 226 | char signame_buf[64]; |
duke@435 | 227 | const char *signame = os::exception_name(_id, signame_buf, sizeof(signame_buf)); |
duke@435 | 228 | |
duke@435 | 229 | if (signame) { |
duke@435 | 230 | jio_snprintf(buf, buflen, |
duke@435 | 231 | "%s (0x%x) at pc=" PTR_FORMAT ", pid=%d, tid=" UINTX_FORMAT, |
duke@435 | 232 | signame, _id, _pc, |
duke@435 | 233 | os::current_process_id(), os::current_thread_id()); |
jcoomes@1845 | 234 | } else if (_filename != NULL && _lineno > 0) { |
jcoomes@1845 | 235 | // skip directory names |
jcoomes@1845 | 236 | char separator = os::file_separator()[0]; |
jcoomes@1845 | 237 | const char *p = strrchr(_filename, separator); |
jcoomes@1845 | 238 | int n = jio_snprintf(buf, buflen, |
jcoomes@1845 | 239 | "Internal Error at %s:%d, pid=%d, tid=" UINTX_FORMAT, |
jcoomes@1845 | 240 | p ? p + 1 : _filename, _lineno, |
jcoomes@1845 | 241 | os::current_process_id(), os::current_thread_id()); |
jcoomes@1845 | 242 | if (n >= 0 && n < buflen && _message) { |
jcoomes@1845 | 243 | if (_detail_msg) { |
jcoomes@1845 | 244 | jio_snprintf(buf + n, buflen - n, "%s%s: %s", |
jcoomes@1845 | 245 | os::line_separator(), _message, _detail_msg); |
jcoomes@1845 | 246 | } else { |
jcoomes@1845 | 247 | jio_snprintf(buf + n, buflen - n, "%sError: %s", |
jcoomes@1845 | 248 | os::line_separator(), _message); |
jcoomes@1845 | 249 | } |
jcoomes@1845 | 250 | } |
duke@435 | 251 | } else { |
jcoomes@1845 | 252 | jio_snprintf(buf, buflen, |
jcoomes@1845 | 253 | "Internal Error (0x%x), pid=%d, tid=" UINTX_FORMAT, |
jcoomes@1845 | 254 | _id, os::current_process_id(), os::current_thread_id()); |
duke@435 | 255 | } |
duke@435 | 256 | |
duke@435 | 257 | return buf; |
duke@435 | 258 | } |
duke@435 | 259 | |
twisti@1819 | 260 | void VMError::print_stack_trace(outputStream* st, JavaThread* jt, |
twisti@1819 | 261 | char* buf, int buflen, bool verbose) { |
twisti@1819 | 262 | #ifdef ZERO |
twisti@1819 | 263 | if (jt->zero_stack()->sp() && jt->top_zero_frame()) { |
twisti@1819 | 264 | // StackFrameStream uses the frame anchor, which may not have |
twisti@1819 | 265 | // been set up. This can be done at any time in Zero, however, |
twisti@1819 | 266 | // so if it hasn't been set up then we just set it up now and |
twisti@1819 | 267 | // clear it again when we're done. |
twisti@1819 | 268 | bool has_last_Java_frame = jt->has_last_Java_frame(); |
twisti@1819 | 269 | if (!has_last_Java_frame) |
twisti@1819 | 270 | jt->set_last_Java_frame(); |
twisti@1819 | 271 | st->print("Java frames:"); |
twisti@1819 | 272 | |
twisti@1819 | 273 | // If the top frame is a Shark frame and the frame anchor isn't |
twisti@1819 | 274 | // set up then it's possible that the information in the frame |
twisti@1819 | 275 | // is garbage: it could be from a previous decache, or it could |
twisti@1819 | 276 | // simply have never been written. So we print a warning... |
twisti@1819 | 277 | StackFrameStream sfs(jt); |
twisti@1819 | 278 | if (!has_last_Java_frame && !sfs.is_done()) { |
twisti@1819 | 279 | if (sfs.current()->zeroframe()->is_shark_frame()) { |
twisti@1819 | 280 | st->print(" (TOP FRAME MAY BE JUNK)"); |
twisti@1819 | 281 | } |
twisti@1819 | 282 | } |
twisti@1819 | 283 | st->cr(); |
twisti@1819 | 284 | |
twisti@1819 | 285 | // Print the frames |
twisti@1819 | 286 | for(int i = 0; !sfs.is_done(); sfs.next(), i++) { |
twisti@1819 | 287 | sfs.current()->zero_print_on_error(i, st, buf, buflen); |
twisti@1819 | 288 | st->cr(); |
twisti@1819 | 289 | } |
twisti@1819 | 290 | |
twisti@1819 | 291 | // Reset the frame anchor if necessary |
twisti@1819 | 292 | if (!has_last_Java_frame) |
twisti@1819 | 293 | jt->reset_last_Java_frame(); |
twisti@1819 | 294 | } |
twisti@1819 | 295 | #else |
twisti@1819 | 296 | if (jt->has_last_Java_frame()) { |
twisti@1819 | 297 | st->print_cr("Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)"); |
twisti@1819 | 298 | for(StackFrameStream sfs(jt); !sfs.is_done(); sfs.next()) { |
twisti@1819 | 299 | sfs.current()->print_on_error(st, buf, buflen, verbose); |
twisti@1819 | 300 | st->cr(); |
twisti@1819 | 301 | } |
twisti@1819 | 302 | } |
twisti@1819 | 303 | #endif // ZERO |
twisti@1819 | 304 | } |
duke@435 | 305 | |
duke@435 | 306 | // This is the main function to report a fatal error. Only one thread can |
duke@435 | 307 | // call this function, so we don't need to worry about MT-safety. But it's |
duke@435 | 308 | // possible that the error handler itself may crash or die on an internal |
duke@435 | 309 | // error, for example, when the stack/heap is badly damaged. We must be |
duke@435 | 310 | // able to handle recursive errors that happen inside error handler. |
duke@435 | 311 | // |
duke@435 | 312 | // Error reporting is done in several steps. If a crash or internal error |
duke@435 | 313 | // occurred when reporting an error, the nested signal/exception handler |
duke@435 | 314 | // can skip steps that are already (or partially) done. Error reporting will |
duke@435 | 315 | // continue from the next step. This allows us to retrieve and print |
duke@435 | 316 | // information that may be unsafe to get after a fatal error. If it happens, |
duke@435 | 317 | // you may find nested report_and_die() frames when you look at the stack |
duke@435 | 318 | // in a debugger. |
duke@435 | 319 | // |
duke@435 | 320 | // In general, a hang in error handler is much worse than a crash or internal |
duke@435 | 321 | // error, as it's harder to recover from a hang. Deadlock can happen if we |
duke@435 | 322 | // try to grab a lock that is already owned by current thread, or if the |
duke@435 | 323 | // owner is blocked forever (e.g. in os::infinite_sleep()). If possible, the |
duke@435 | 324 | // error handler and all the functions it called should avoid grabbing any |
duke@435 | 325 | // lock. An important thing to notice is that memory allocation needs a lock. |
duke@435 | 326 | // |
duke@435 | 327 | // We should avoid using large stack allocated buffers. Many errors happen |
duke@435 | 328 | // when stack space is already low. Making things even worse is that there |
duke@435 | 329 | // could be nested report_and_die() calls on stack (see above). Only one |
duke@435 | 330 | // thread can report error, so large buffers are statically allocated in data |
duke@435 | 331 | // segment. |
duke@435 | 332 | |
duke@435 | 333 | void VMError::report(outputStream* st) { |
duke@435 | 334 | # define BEGIN if (_current_step == 0) { _current_step = 1; |
duke@435 | 335 | # define STEP(n, s) } if (_current_step < n) { _current_step = n; _current_step_info = s; |
duke@435 | 336 | # define END } |
duke@435 | 337 | |
duke@435 | 338 | // don't allocate large buffer on stack |
duke@435 | 339 | static char buf[O_BUFLEN]; |
duke@435 | 340 | |
duke@435 | 341 | BEGIN |
duke@435 | 342 | |
coleenp@491 | 343 | STEP(10, "(printing fatal error message)") |
duke@435 | 344 | |
coleenp@2418 | 345 | st->print_cr("#"); |
coleenp@2418 | 346 | if (should_report_bug(_id)) { |
coleenp@2418 | 347 | st->print_cr("# A fatal error has been detected by the Java Runtime Environment:"); |
coleenp@2418 | 348 | } else { |
coleenp@2418 | 349 | st->print_cr("# There is insufficient memory for the Java " |
coleenp@2418 | 350 | "Runtime Environment to continue."); |
coleenp@2418 | 351 | } |
duke@435 | 352 | |
duke@435 | 353 | STEP(15, "(printing type of error)") |
duke@435 | 354 | |
duke@435 | 355 | switch(_id) { |
ccheung@4993 | 356 | case OOM_MALLOC_ERROR: |
ccheung@4993 | 357 | case OOM_MMAP_ERROR: |
duke@435 | 358 | if (_size) { |
ccheung@4993 | 359 | st->print("# Native memory allocation "); |
ccheung@4993 | 360 | st->print((_id == (int)OOM_MALLOC_ERROR) ? "(malloc) failed to allocate " : |
ccheung@4993 | 361 | "(mmap) failed to map "); |
coleenp@2418 | 362 | jio_snprintf(buf, sizeof(buf), SIZE_FORMAT, _size); |
drchase@6680 | 363 | st->print("%s", buf); |
duke@435 | 364 | st->print(" bytes"); |
duke@435 | 365 | if (_message != NULL) { |
duke@435 | 366 | st->print(" for "); |
drchase@6680 | 367 | st->print("%s", _message); |
duke@435 | 368 | } |
coleenp@2418 | 369 | st->cr(); |
duke@435 | 370 | } else { |
duke@435 | 371 | if (_message != NULL) |
coleenp@2418 | 372 | st->print("# "); |
drchase@6680 | 373 | st->print_cr("%s", _message); |
duke@435 | 374 | } |
coleenp@2418 | 375 | // In error file give some solutions |
coleenp@2418 | 376 | if (_verbose) { |
coleenp@2418 | 377 | st->print_cr("# Possible reasons:"); |
coleenp@2418 | 378 | st->print_cr("# The system is out of physical RAM or swap space"); |
coleenp@2418 | 379 | st->print_cr("# In 32 bit mode, the process size limit was hit"); |
coleenp@2418 | 380 | st->print_cr("# Possible solutions:"); |
coleenp@2418 | 381 | st->print_cr("# Reduce memory load on the system"); |
coleenp@2418 | 382 | st->print_cr("# Increase physical memory or swap space"); |
coleenp@2418 | 383 | st->print_cr("# Check if swap backing store is full"); |
coleenp@2418 | 384 | st->print_cr("# Use 64 bit Java on a 64 bit OS"); |
coleenp@2418 | 385 | st->print_cr("# Decrease Java heap size (-Xmx/-Xms)"); |
coleenp@2418 | 386 | st->print_cr("# Decrease number of Java threads"); |
coleenp@2418 | 387 | st->print_cr("# Decrease Java thread stack sizes (-Xss)"); |
coleenp@2418 | 388 | st->print_cr("# Set larger code cache with -XX:ReservedCodeCacheSize="); |
coleenp@2418 | 389 | st->print_cr("# This output file may be truncated or incomplete."); |
coleenp@2418 | 390 | } else { |
coleenp@2418 | 391 | return; // that's enough for the screen |
coleenp@2418 | 392 | } |
duke@435 | 393 | break; |
ccheung@4993 | 394 | case INTERNAL_ERROR: |
duke@435 | 395 | default: |
duke@435 | 396 | break; |
duke@435 | 397 | } |
duke@435 | 398 | |
duke@435 | 399 | STEP(20, "(printing exception/signal name)") |
duke@435 | 400 | |
duke@435 | 401 | st->print_cr("#"); |
duke@435 | 402 | st->print("# "); |
duke@435 | 403 | // Is it an OS exception/signal? |
duke@435 | 404 | if (os::exception_name(_id, buf, sizeof(buf))) { |
duke@435 | 405 | st->print("%s", buf); |
duke@435 | 406 | st->print(" (0x%x)", _id); // signal number |
duke@435 | 407 | st->print(" at pc=" PTR_FORMAT, _pc); |
duke@435 | 408 | } else { |
coleenp@2418 | 409 | if (should_report_bug(_id)) { |
coleenp@2418 | 410 | st->print("Internal Error"); |
coleenp@2418 | 411 | } else { |
coleenp@2418 | 412 | st->print("Out of Memory Error"); |
coleenp@2418 | 413 | } |
duke@435 | 414 | if (_filename != NULL && _lineno > 0) { |
duke@435 | 415 | #ifdef PRODUCT |
duke@435 | 416 | // In product mode chop off pathname? |
duke@435 | 417 | char separator = os::file_separator()[0]; |
duke@435 | 418 | const char *p = strrchr(_filename, separator); |
duke@435 | 419 | const char *file = p ? p+1 : _filename; |
duke@435 | 420 | #else |
duke@435 | 421 | const char *file = _filename; |
duke@435 | 422 | #endif |
duke@435 | 423 | size_t len = strlen(file); |
duke@435 | 424 | size_t buflen = sizeof(buf); |
duke@435 | 425 | |
duke@435 | 426 | strncpy(buf, file, buflen); |
duke@435 | 427 | if (len + 10 < buflen) { |
twisti@1038 | 428 | sprintf(buf + len, ":%d", _lineno); |
duke@435 | 429 | } |
duke@435 | 430 | st->print(" (%s)", buf); |
duke@435 | 431 | } else { |
duke@435 | 432 | st->print(" (0x%x)", _id); |
duke@435 | 433 | } |
duke@435 | 434 | } |
duke@435 | 435 | |
duke@435 | 436 | STEP(30, "(printing current thread and pid)") |
duke@435 | 437 | |
duke@435 | 438 | // process id, thread id |
duke@435 | 439 | st->print(", pid=%d", os::current_process_id()); |
duke@435 | 440 | st->print(", tid=" UINTX_FORMAT, os::current_thread_id()); |
duke@435 | 441 | st->cr(); |
duke@435 | 442 | |
duke@435 | 443 | STEP(40, "(printing error message)") |
duke@435 | 444 | |
coleenp@2418 | 445 | if (should_report_bug(_id)) { // already printed the message. |
coleenp@2418 | 446 | // error message |
coleenp@2418 | 447 | if (_detail_msg) { |
coleenp@2418 | 448 | st->print_cr("# %s: %s", _message ? _message : "Error", _detail_msg); |
coleenp@2418 | 449 | } else if (_message) { |
coleenp@2418 | 450 | st->print_cr("# Error: %s", _message); |
coleenp@2418 | 451 | } |
coleenp@2418 | 452 | } |
duke@435 | 453 | |
duke@435 | 454 | STEP(50, "(printing Java version string)") |
duke@435 | 455 | |
duke@435 | 456 | // VM version |
duke@435 | 457 | st->print_cr("#"); |
coleenp@908 | 458 | JDK_Version::current().to_string(buf, sizeof(buf)); |
twisti@3884 | 459 | const char* runtime_name = JDK_Version::runtime_name() != NULL ? |
twisti@3884 | 460 | JDK_Version::runtime_name() : ""; |
sla@4232 | 461 | const char* runtime_version = JDK_Version::runtime_version() != NULL ? |
sla@4232 | 462 | JDK_Version::runtime_version() : ""; |
sla@4232 | 463 | st->print_cr("# JRE version: %s (%s) (build %s)", runtime_name, buf, runtime_version); |
coleenp@548 | 464 | st->print_cr("# Java VM: %s (%s %s %s %s)", |
duke@435 | 465 | Abstract_VM_Version::vm_name(), |
duke@435 | 466 | Abstract_VM_Version::vm_release(), |
duke@435 | 467 | Abstract_VM_Version::vm_info_string(), |
coleenp@548 | 468 | Abstract_VM_Version::vm_platform_string(), |
coleenp@548 | 469 | UseCompressedOops ? "compressed oops" : "" |
duke@435 | 470 | ); |
duke@435 | 471 | |
duke@435 | 472 | STEP(60, "(printing problematic frame)") |
duke@435 | 473 | |
duke@435 | 474 | // Print current frame if we have a context (i.e. it's a crash) |
duke@435 | 475 | if (_context) { |
duke@435 | 476 | st->print_cr("# Problematic frame:"); |
duke@435 | 477 | st->print("# "); |
duke@435 | 478 | frame fr = os::fetch_frame_from_context(_context); |
duke@435 | 479 | fr.print_on_error(st, buf, sizeof(buf)); |
duke@435 | 480 | st->cr(); |
duke@435 | 481 | st->print_cr("#"); |
duke@435 | 482 | } |
ctornqvi@2520 | 483 | STEP(63, "(printing core file information)") |
ctornqvi@2520 | 484 | st->print("# "); |
ctornqvi@2520 | 485 | if (coredump_status) { |
ctornqvi@2520 | 486 | st->print("Core dump written. Default location: %s", coredump_message); |
ctornqvi@2520 | 487 | } else { |
ctornqvi@2520 | 488 | st->print("Failed to write core dump. %s", coredump_message); |
ctornqvi@2520 | 489 | } |
drchase@6680 | 490 | st->cr(); |
ctornqvi@2520 | 491 | st->print_cr("#"); |
duke@435 | 492 | |
duke@435 | 493 | STEP(65, "(printing bug submit message)") |
duke@435 | 494 | |
coleenp@2418 | 495 | if (should_report_bug(_id) && _verbose) { |
coleenp@2418 | 496 | print_bug_submit_message(st, _thread); |
coleenp@2418 | 497 | } |
duke@435 | 498 | |
duke@435 | 499 | STEP(70, "(printing thread)" ) |
duke@435 | 500 | |
duke@435 | 501 | if (_verbose) { |
duke@435 | 502 | st->cr(); |
duke@435 | 503 | st->print_cr("--------------- T H R E A D ---------------"); |
duke@435 | 504 | st->cr(); |
duke@435 | 505 | } |
duke@435 | 506 | |
duke@435 | 507 | STEP(80, "(printing current thread)" ) |
duke@435 | 508 | |
duke@435 | 509 | // current thread |
duke@435 | 510 | if (_verbose) { |
duke@435 | 511 | if (_thread) { |
duke@435 | 512 | st->print("Current thread (" PTR_FORMAT "): ", _thread); |
duke@435 | 513 | _thread->print_on_error(st, buf, sizeof(buf)); |
duke@435 | 514 | st->cr(); |
duke@435 | 515 | } else { |
duke@435 | 516 | st->print_cr("Current thread is native thread"); |
duke@435 | 517 | } |
duke@435 | 518 | st->cr(); |
duke@435 | 519 | } |
duke@435 | 520 | |
duke@435 | 521 | STEP(90, "(printing siginfo)" ) |
duke@435 | 522 | |
duke@435 | 523 | // signal no, signal code, address that caused the fault |
duke@435 | 524 | if (_verbose && _siginfo) { |
duke@435 | 525 | os::print_siginfo(st, _siginfo); |
duke@435 | 526 | st->cr(); |
duke@435 | 527 | } |
duke@435 | 528 | |
duke@435 | 529 | STEP(100, "(printing registers, top of stack, instructions near pc)") |
duke@435 | 530 | |
duke@435 | 531 | // registers, top of stack, instructions near pc |
duke@435 | 532 | if (_verbose && _context) { |
duke@435 | 533 | os::print_context(st, _context); |
duke@435 | 534 | st->cr(); |
duke@435 | 535 | } |
duke@435 | 536 | |
never@2262 | 537 | STEP(105, "(printing register info)") |
never@2262 | 538 | |
never@2262 | 539 | // decode register contents if possible |
never@2262 | 540 | if (_verbose && _context && Universe::is_fully_initialized()) { |
never@2262 | 541 | os::print_register_info(st, _context); |
never@2262 | 542 | st->cr(); |
never@2262 | 543 | } |
never@2262 | 544 | |
duke@435 | 545 | STEP(110, "(printing stack bounds)" ) |
duke@435 | 546 | |
duke@435 | 547 | if (_verbose) { |
duke@435 | 548 | st->print("Stack: "); |
duke@435 | 549 | |
duke@435 | 550 | address stack_top; |
duke@435 | 551 | size_t stack_size; |
duke@435 | 552 | |
duke@435 | 553 | if (_thread) { |
duke@435 | 554 | stack_top = _thread->stack_base(); |
duke@435 | 555 | stack_size = _thread->stack_size(); |
duke@435 | 556 | } else { |
duke@435 | 557 | stack_top = os::current_stack_base(); |
duke@435 | 558 | stack_size = os::current_stack_size(); |
duke@435 | 559 | } |
duke@435 | 560 | |
duke@435 | 561 | address stack_bottom = stack_top - stack_size; |
duke@435 | 562 | st->print("[" PTR_FORMAT "," PTR_FORMAT "]", stack_bottom, stack_top); |
duke@435 | 563 | |
duke@435 | 564 | frame fr = _context ? os::fetch_frame_from_context(_context) |
duke@435 | 565 | : os::current_frame(); |
duke@435 | 566 | |
duke@435 | 567 | if (fr.sp()) { |
duke@435 | 568 | st->print(", sp=" PTR_FORMAT, fr.sp()); |
kvn@2039 | 569 | size_t free_stack_size = pointer_delta(fr.sp(), stack_bottom, 1024); |
kvn@2039 | 570 | st->print(", free space=" SIZE_FORMAT "k", free_stack_size); |
duke@435 | 571 | } |
duke@435 | 572 | |
duke@435 | 573 | st->cr(); |
duke@435 | 574 | } |
duke@435 | 575 | |
duke@435 | 576 | STEP(120, "(printing native stack)" ) |
duke@435 | 577 | |
duke@435 | 578 | if (_verbose) { |
iklam@5667 | 579 | if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) { |
iklam@5667 | 580 | // We have printed the native stack in platform-specific code |
iklam@5667 | 581 | // Windows/x64 needs special handling. |
iklam@5667 | 582 | } else { |
duke@435 | 583 | frame fr = _context ? os::fetch_frame_from_context(_context) |
duke@435 | 584 | : os::current_frame(); |
duke@435 | 585 | |
duke@435 | 586 | // see if it's a valid frame |
duke@435 | 587 | if (fr.pc()) { |
duke@435 | 588 | st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); |
duke@435 | 589 | |
zgu@2364 | 590 | |
duke@435 | 591 | int count = 0; |
duke@435 | 592 | while (count++ < StackPrintLimit) { |
duke@435 | 593 | fr.print_on_error(st, buf, sizeof(buf)); |
duke@435 | 594 | st->cr(); |
kvn@5543 | 595 | // Compiled code may use EBP register on x86 so it looks like |
kvn@5543 | 596 | // non-walkable C frame. Use frame.sender() for java frames. |
kvn@6357 | 597 | if (_thread && _thread->is_Java_thread()) { |
kvn@6357 | 598 | // Catch very first native frame by using stack address. |
kvn@6357 | 599 | // For JavaThread stack_base and stack_size should be set. |
kvn@6357 | 600 | if (!_thread->on_local_stack((address)(fr.sender_sp() + 1))) { |
kvn@6357 | 601 | break; |
kvn@6357 | 602 | } |
kvn@6357 | 603 | if (fr.is_java_frame()) { |
kvn@6357 | 604 | RegisterMap map((JavaThread*)_thread, false); // No update |
kvn@6357 | 605 | fr = fr.sender(&map); |
kvn@6357 | 606 | } else { |
kvn@6357 | 607 | fr = os::get_sender_for_C_frame(&fr); |
kvn@6357 | 608 | } |
kvn@6357 | 609 | } else { |
kvn@6357 | 610 | // is_first_C_frame() does only simple checks for frame pointer, |
kvn@6357 | 611 | // it will pass if java compiled code has a pointer in EBP. |
kvn@6357 | 612 | if (os::is_first_C_frame(&fr)) break; |
kvn@6357 | 613 | fr = os::get_sender_for_C_frame(&fr); |
kvn@5543 | 614 | } |
duke@435 | 615 | } |
duke@435 | 616 | |
duke@435 | 617 | if (count > StackPrintLimit) { |
duke@435 | 618 | st->print_cr("...<more frames>..."); |
duke@435 | 619 | } |
duke@435 | 620 | |
duke@435 | 621 | st->cr(); |
duke@435 | 622 | } |
duke@435 | 623 | } |
iklam@5667 | 624 | } |
duke@435 | 625 | |
duke@435 | 626 | STEP(130, "(printing Java stack)" ) |
duke@435 | 627 | |
duke@435 | 628 | if (_verbose && _thread && _thread->is_Java_thread()) { |
twisti@1819 | 629 | print_stack_trace(st, (JavaThread*)_thread, buf, sizeof(buf)); |
duke@435 | 630 | } |
duke@435 | 631 | |
minqi@1554 | 632 | STEP(135, "(printing target Java thread stack)" ) |
minqi@1554 | 633 | |
minqi@1554 | 634 | // printing Java thread stack trace if it is involved in GC crash |
never@2262 | 635 | if (_verbose && _thread && (_thread->is_Named_thread())) { |
minqi@1554 | 636 | JavaThread* jt = ((NamedThread *)_thread)->processed_thread(); |
minqi@1554 | 637 | if (jt != NULL) { |
minqi@1554 | 638 | st->print_cr("JavaThread " PTR_FORMAT " (nid = " UINTX_FORMAT ") was being processed", jt, jt->osthread()->thread_id()); |
twisti@1819 | 639 | print_stack_trace(st, jt, buf, sizeof(buf), true); |
minqi@1554 | 640 | } |
minqi@1554 | 641 | } |
minqi@1554 | 642 | |
duke@435 | 643 | STEP(140, "(printing VM operation)" ) |
duke@435 | 644 | |
duke@435 | 645 | if (_verbose && _thread && _thread->is_VM_thread()) { |
duke@435 | 646 | VMThread* t = (VMThread*)_thread; |
duke@435 | 647 | VM_Operation* op = t->vm_operation(); |
duke@435 | 648 | if (op) { |
duke@435 | 649 | op->print_on_error(st); |
duke@435 | 650 | st->cr(); |
duke@435 | 651 | st->cr(); |
duke@435 | 652 | } |
duke@435 | 653 | } |
duke@435 | 654 | |
duke@435 | 655 | STEP(150, "(printing current compile task)" ) |
duke@435 | 656 | |
duke@435 | 657 | if (_verbose && _thread && _thread->is_Compiler_thread()) { |
duke@435 | 658 | CompilerThread* t = (CompilerThread*)_thread; |
duke@435 | 659 | if (t->task()) { |
duke@435 | 660 | st->cr(); |
duke@435 | 661 | st->print_cr("Current CompileTask:"); |
duke@435 | 662 | t->task()->print_line_on_error(st, buf, sizeof(buf)); |
duke@435 | 663 | st->cr(); |
duke@435 | 664 | } |
duke@435 | 665 | } |
duke@435 | 666 | |
duke@435 | 667 | STEP(160, "(printing process)" ) |
duke@435 | 668 | |
duke@435 | 669 | if (_verbose) { |
duke@435 | 670 | st->cr(); |
duke@435 | 671 | st->print_cr("--------------- P R O C E S S ---------------"); |
duke@435 | 672 | st->cr(); |
duke@435 | 673 | } |
duke@435 | 674 | |
duke@435 | 675 | STEP(170, "(printing all threads)" ) |
duke@435 | 676 | |
duke@435 | 677 | // all threads |
duke@435 | 678 | if (_verbose && _thread) { |
duke@435 | 679 | Threads::print_on_error(st, _thread, buf, sizeof(buf)); |
duke@435 | 680 | st->cr(); |
duke@435 | 681 | } |
duke@435 | 682 | |
duke@435 | 683 | STEP(175, "(printing VM state)" ) |
duke@435 | 684 | |
duke@435 | 685 | if (_verbose) { |
duke@435 | 686 | // Safepoint state |
duke@435 | 687 | st->print("VM state:"); |
duke@435 | 688 | |
duke@435 | 689 | if (SafepointSynchronize::is_synchronizing()) st->print("synchronizing"); |
duke@435 | 690 | else if (SafepointSynchronize::is_at_safepoint()) st->print("at safepoint"); |
duke@435 | 691 | else st->print("not at safepoint"); |
duke@435 | 692 | |
duke@435 | 693 | // Also see if error occurred during initialization or shutdown |
duke@435 | 694 | if (!Universe::is_fully_initialized()) { |
duke@435 | 695 | st->print(" (not fully initialized)"); |
duke@435 | 696 | } else if (VM_Exit::vm_exited()) { |
duke@435 | 697 | st->print(" (shutting down)"); |
duke@435 | 698 | } else { |
duke@435 | 699 | st->print(" (normal execution)"); |
duke@435 | 700 | } |
duke@435 | 701 | st->cr(); |
duke@435 | 702 | st->cr(); |
duke@435 | 703 | } |
duke@435 | 704 | |
duke@435 | 705 | STEP(180, "(printing owned locks on error)" ) |
duke@435 | 706 | |
duke@435 | 707 | // mutexes/monitors that currently have an owner |
duke@435 | 708 | if (_verbose) { |
duke@435 | 709 | print_owned_locks_on_error(st); |
duke@435 | 710 | st->cr(); |
duke@435 | 711 | } |
duke@435 | 712 | |
duke@435 | 713 | STEP(190, "(printing heap information)" ) |
duke@435 | 714 | |
duke@435 | 715 | if (_verbose && Universe::is_fully_initialized()) { |
stefank@4904 | 716 | Universe::heap()->print_on_error(st); |
never@3687 | 717 | st->cr(); |
never@3687 | 718 | |
never@3687 | 719 | st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page()); |
never@3687 | 720 | st->cr(); |
duke@435 | 721 | } |
duke@435 | 722 | |
never@2262 | 723 | STEP(195, "(printing code cache information)" ) |
never@2262 | 724 | |
never@2262 | 725 | if (_verbose && Universe::is_fully_initialized()) { |
never@2262 | 726 | // print code cache information before vm abort |
vladidan@4438 | 727 | CodeCache::print_summary(st); |
never@2262 | 728 | st->cr(); |
never@2262 | 729 | } |
never@2262 | 730 | |
never@3499 | 731 | STEP(200, "(printing ring buffers)" ) |
never@3499 | 732 | |
never@3499 | 733 | if (_verbose) { |
never@3499 | 734 | Events::print_all(st); |
never@3499 | 735 | st->cr(); |
never@3499 | 736 | } |
never@3499 | 737 | |
never@3499 | 738 | STEP(205, "(printing dynamic libraries)" ) |
duke@435 | 739 | |
duke@435 | 740 | if (_verbose) { |
duke@435 | 741 | // dynamic libraries, or memory map |
duke@435 | 742 | os::print_dll_info(st); |
duke@435 | 743 | st->cr(); |
duke@435 | 744 | } |
duke@435 | 745 | |
duke@435 | 746 | STEP(210, "(printing VM options)" ) |
duke@435 | 747 | |
duke@435 | 748 | if (_verbose) { |
duke@435 | 749 | // VM options |
duke@435 | 750 | Arguments::print_on(st); |
duke@435 | 751 | st->cr(); |
duke@435 | 752 | } |
duke@435 | 753 | |
mgerdin@3619 | 754 | STEP(215, "(printing warning if internal testing API used)" ) |
mgerdin@3619 | 755 | |
mgerdin@3619 | 756 | if (WhiteBox::used()) { |
mgerdin@3619 | 757 | st->print_cr("Unsupported internal testing APIs have been used."); |
mgerdin@3619 | 758 | st->cr(); |
mgerdin@3619 | 759 | } |
mgerdin@3619 | 760 | |
duke@435 | 761 | STEP(220, "(printing environment variables)" ) |
duke@435 | 762 | |
duke@435 | 763 | if (_verbose) { |
duke@435 | 764 | os::print_environment_variables(st, env_list, buf, sizeof(buf)); |
duke@435 | 765 | st->cr(); |
duke@435 | 766 | } |
duke@435 | 767 | |
duke@435 | 768 | STEP(225, "(printing signal handlers)" ) |
duke@435 | 769 | |
duke@435 | 770 | if (_verbose) { |
duke@435 | 771 | os::print_signal_handlers(st, buf, sizeof(buf)); |
duke@435 | 772 | st->cr(); |
duke@435 | 773 | } |
duke@435 | 774 | |
zgu@7074 | 775 | STEP(228, "(Native Memory Tracking)" ) |
zgu@7074 | 776 | if (_verbose) { |
zgu@7074 | 777 | MemTracker::final_report(st); |
zgu@7074 | 778 | } |
zgu@7074 | 779 | |
duke@435 | 780 | STEP(230, "" ) |
duke@435 | 781 | |
duke@435 | 782 | if (_verbose) { |
duke@435 | 783 | st->cr(); |
duke@435 | 784 | st->print_cr("--------------- S Y S T E M ---------------"); |
duke@435 | 785 | st->cr(); |
duke@435 | 786 | } |
duke@435 | 787 | |
duke@435 | 788 | STEP(240, "(printing OS information)" ) |
duke@435 | 789 | |
duke@435 | 790 | if (_verbose) { |
duke@435 | 791 | os::print_os_info(st); |
duke@435 | 792 | st->cr(); |
duke@435 | 793 | } |
duke@435 | 794 | |
duke@435 | 795 | STEP(250, "(printing CPU info)" ) |
duke@435 | 796 | if (_verbose) { |
duke@435 | 797 | os::print_cpu_info(st); |
duke@435 | 798 | st->cr(); |
duke@435 | 799 | } |
duke@435 | 800 | |
duke@435 | 801 | STEP(260, "(printing memory info)" ) |
duke@435 | 802 | |
duke@435 | 803 | if (_verbose) { |
duke@435 | 804 | os::print_memory_info(st); |
duke@435 | 805 | st->cr(); |
duke@435 | 806 | } |
duke@435 | 807 | |
duke@435 | 808 | STEP(270, "(printing internal vm info)" ) |
duke@435 | 809 | |
duke@435 | 810 | if (_verbose) { |
duke@435 | 811 | st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string()); |
duke@435 | 812 | st->cr(); |
duke@435 | 813 | } |
duke@435 | 814 | |
duke@435 | 815 | STEP(280, "(printing date and time)" ) |
duke@435 | 816 | |
duke@435 | 817 | if (_verbose) { |
duke@435 | 818 | os::print_date_and_time(st); |
duke@435 | 819 | st->cr(); |
duke@435 | 820 | } |
duke@435 | 821 | |
duke@435 | 822 | END |
duke@435 | 823 | |
duke@435 | 824 | # undef BEGIN |
duke@435 | 825 | # undef STEP |
duke@435 | 826 | # undef END |
duke@435 | 827 | } |
duke@435 | 828 | |
bobv@2036 | 829 | VMError* volatile VMError::first_error = NULL; |
bobv@2036 | 830 | volatile jlong VMError::first_error_tid = -1; |
duke@435 | 831 | |
fparain@5333 | 832 | // An error could happen before tty is initialized or after it has been |
fparain@5333 | 833 | // destroyed. Here we use a very simple unbuffered fdStream for printing. |
fparain@5333 | 834 | // Only out.print_raw() and out.print_raw_cr() should be used, as other |
fparain@5333 | 835 | // printing methods need to allocate large buffer on stack. To format a |
fparain@5333 | 836 | // string, use jio_snprintf() with a static buffer or use staticBufferStream. |
fparain@5333 | 837 | fdStream VMError::out(defaultStream::output_fd()); |
fparain@5333 | 838 | fdStream VMError::log; // error log used by VMError::report_and_die() |
fparain@5333 | 839 | |
vlivanov@5027 | 840 | /** Expand a pattern into a buffer starting at pos and open a file using constructed path */ |
vlivanov@5027 | 841 | static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) { |
vlivanov@5027 | 842 | int fd = -1; |
vlivanov@5027 | 843 | if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) { |
vlivanov@5027 | 844 | fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666); |
vlivanov@5027 | 845 | } |
vlivanov@5027 | 846 | return fd; |
vlivanov@5027 | 847 | } |
vlivanov@5027 | 848 | |
vlivanov@5027 | 849 | /** |
vlivanov@5027 | 850 | * Construct file name for a log file and return it's file descriptor. |
vlivanov@5027 | 851 | * Name and location depends on pattern, default_pattern params and access |
vlivanov@5027 | 852 | * permissions. |
vlivanov@5027 | 853 | */ |
vlivanov@5027 | 854 | static int prepare_log_file(const char* pattern, const char* default_pattern, char* buf, size_t buflen) { |
vlivanov@5027 | 855 | int fd = -1; |
vlivanov@5027 | 856 | |
vlivanov@5027 | 857 | // If possible, use specified pattern to construct log file name |
vlivanov@5027 | 858 | if (pattern != NULL) { |
vlivanov@5027 | 859 | fd = expand_and_open(pattern, buf, buflen, 0); |
vlivanov@5027 | 860 | } |
vlivanov@5027 | 861 | |
vlivanov@5027 | 862 | // Either user didn't specify, or the user's location failed, |
vlivanov@5027 | 863 | // so use the default name in the current directory |
vlivanov@5027 | 864 | if (fd == -1) { |
vlivanov@5027 | 865 | const char* cwd = os::get_current_directory(buf, buflen); |
vlivanov@5027 | 866 | if (cwd != NULL) { |
vlivanov@5027 | 867 | size_t pos = strlen(cwd); |
vlivanov@5027 | 868 | int fsep_len = jio_snprintf(&buf[pos], buflen-pos, "%s", os::file_separator()); |
vlivanov@5027 | 869 | pos += fsep_len; |
vlivanov@5027 | 870 | if (fsep_len > 0) { |
vlivanov@5027 | 871 | fd = expand_and_open(default_pattern, buf, buflen, pos); |
vlivanov@5027 | 872 | } |
vlivanov@5027 | 873 | } |
vlivanov@5027 | 874 | } |
vlivanov@5027 | 875 | |
vlivanov@5027 | 876 | // try temp directory if it exists. |
vlivanov@5027 | 877 | if (fd == -1) { |
vlivanov@5027 | 878 | const char* tmpdir = os::get_temp_directory(); |
vlivanov@5027 | 879 | if (tmpdir != NULL && strlen(tmpdir) > 0) { |
vlivanov@5027 | 880 | int pos = jio_snprintf(buf, buflen, "%s%s", tmpdir, os::file_separator()); |
vlivanov@5027 | 881 | if (pos > 0) { |
vlivanov@5027 | 882 | fd = expand_and_open(default_pattern, buf, buflen, pos); |
vlivanov@5027 | 883 | } |
vlivanov@5027 | 884 | } |
vlivanov@5027 | 885 | } |
vlivanov@5027 | 886 | |
vlivanov@5027 | 887 | return fd; |
vlivanov@5027 | 888 | } |
vlivanov@5027 | 889 | |
duke@435 | 890 | void VMError::report_and_die() { |
duke@435 | 891 | // Don't allocate large buffer on stack |
duke@435 | 892 | static char buffer[O_BUFLEN]; |
duke@435 | 893 | |
duke@435 | 894 | // How many errors occurred in error handler when reporting first_error. |
duke@435 | 895 | static int recursive_error_count; |
duke@435 | 896 | |
duke@435 | 897 | // We will first print a brief message to standard out (verbose = false), |
duke@435 | 898 | // then save detailed information in log file (verbose = true). |
duke@435 | 899 | static bool out_done = false; // done printing to standard out |
duke@435 | 900 | static bool log_done = false; // done saving error log |
kamg@2515 | 901 | static bool transmit_report_done = false; // done error reporting |
duke@435 | 902 | |
duke@435 | 903 | if (SuppressFatalErrorMessage) { |
duke@435 | 904 | os::abort(); |
duke@435 | 905 | } |
duke@435 | 906 | jlong mytid = os::current_thread_id(); |
duke@435 | 907 | if (first_error == NULL && |
duke@435 | 908 | Atomic::cmpxchg_ptr(this, &first_error, NULL) == NULL) { |
duke@435 | 909 | |
duke@435 | 910 | // first time |
duke@435 | 911 | first_error_tid = mytid; |
duke@435 | 912 | set_error_reported(); |
duke@435 | 913 | |
sla@2584 | 914 | if (ShowMessageBoxOnError || PauseAtExit) { |
duke@435 | 915 | show_message_box(buffer, sizeof(buffer)); |
duke@435 | 916 | |
duke@435 | 917 | // User has asked JVM to abort. Reset ShowMessageBoxOnError so the |
duke@435 | 918 | // WatcherThread can kill JVM if the error handler hangs. |
duke@435 | 919 | ShowMessageBoxOnError = false; |
duke@435 | 920 | } |
duke@435 | 921 | |
ctornqvi@2520 | 922 | // Write a minidump on Windows, check core dump limits on Linux/Solaris |
ctornqvi@2520 | 923 | os::check_or_create_dump(_siginfo, _context, buffer, sizeof(buffer)); |
ctornqvi@2520 | 924 | |
duke@435 | 925 | // reset signal handlers or exception filter; make sure recursive crashes |
duke@435 | 926 | // are handled properly. |
duke@435 | 927 | reset_signal_handlers(); |
duke@435 | 928 | |
duke@435 | 929 | } else { |
coleenp@946 | 930 | // If UseOsErrorReporting we call this for each level of the call stack |
coleenp@946 | 931 | // while searching for the exception handler. Only the first level needs |
coleenp@946 | 932 | // to be reported. |
coleenp@946 | 933 | if (UseOSErrorReporting && log_done) return; |
coleenp@946 | 934 | |
duke@435 | 935 | // This is not the first error, see if it happened in a different thread |
duke@435 | 936 | // or in the same thread during error reporting. |
duke@435 | 937 | if (first_error_tid != mytid) { |
fparain@5366 | 938 | char msgbuf[64]; |
fparain@5366 | 939 | jio_snprintf(msgbuf, sizeof(msgbuf), |
duke@435 | 940 | "[thread " INT64_FORMAT " also had an error]", |
duke@435 | 941 | mytid); |
fparain@5366 | 942 | out.print_raw_cr(msgbuf); |
duke@435 | 943 | |
duke@435 | 944 | // error reporting is not MT-safe, block current thread |
duke@435 | 945 | os::infinite_sleep(); |
duke@435 | 946 | |
duke@435 | 947 | } else { |
duke@435 | 948 | if (recursive_error_count++ > 30) { |
duke@435 | 949 | out.print_raw_cr("[Too many errors, abort]"); |
duke@435 | 950 | os::die(); |
duke@435 | 951 | } |
duke@435 | 952 | |
duke@435 | 953 | jio_snprintf(buffer, sizeof(buffer), |
duke@435 | 954 | "[error occurred during error reporting %s, id 0x%x]", |
duke@435 | 955 | first_error ? first_error->_current_step_info : "", |
duke@435 | 956 | _id); |
duke@435 | 957 | if (log.is_open()) { |
duke@435 | 958 | log.cr(); |
duke@435 | 959 | log.print_raw_cr(buffer); |
duke@435 | 960 | log.cr(); |
duke@435 | 961 | } else { |
duke@435 | 962 | out.cr(); |
duke@435 | 963 | out.print_raw_cr(buffer); |
duke@435 | 964 | out.cr(); |
duke@435 | 965 | } |
duke@435 | 966 | } |
duke@435 | 967 | } |
duke@435 | 968 | |
duke@435 | 969 | // print to screen |
duke@435 | 970 | if (!out_done) { |
duke@435 | 971 | first_error->_verbose = false; |
duke@435 | 972 | |
duke@435 | 973 | staticBufferStream sbs(buffer, sizeof(buffer), &out); |
duke@435 | 974 | first_error->report(&sbs); |
duke@435 | 975 | |
duke@435 | 976 | out_done = true; |
duke@435 | 977 | |
duke@435 | 978 | first_error->_current_step = 0; // reset current_step |
duke@435 | 979 | first_error->_current_step_info = ""; // reset current_step string |
duke@435 | 980 | } |
duke@435 | 981 | |
duke@435 | 982 | // print to error log file |
duke@435 | 983 | if (!log_done) { |
duke@435 | 984 | first_error->_verbose = true; |
duke@435 | 985 | |
duke@435 | 986 | // see if log file is already open |
duke@435 | 987 | if (!log.is_open()) { |
duke@435 | 988 | // open log file |
vlivanov@5027 | 989 | int fd = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer)); |
duke@435 | 990 | if (fd != -1) { |
duke@435 | 991 | out.print_raw("# An error report file with more information is saved as:\n# "); |
duke@435 | 992 | out.print_raw_cr(buffer); |
duke@435 | 993 | |
duke@435 | 994 | log.set_fd(fd); |
duke@435 | 995 | } else { |
duke@435 | 996 | out.print_raw_cr("# Can not save log file, dump to screen.."); |
duke@435 | 997 | log.set_fd(defaultStream::output_fd()); |
kamg@2515 | 998 | /* Error reporting currently needs dumpfile. |
kamg@2515 | 999 | * Maybe implement direct streaming in the future.*/ |
kamg@2515 | 1000 | transmit_report_done = true; |
duke@435 | 1001 | } |
duke@435 | 1002 | } |
duke@435 | 1003 | |
duke@435 | 1004 | staticBufferStream sbs(buffer, O_BUFLEN, &log); |
duke@435 | 1005 | first_error->report(&sbs); |
duke@435 | 1006 | first_error->_current_step = 0; // reset current_step |
duke@435 | 1007 | first_error->_current_step_info = ""; // reset current_step string |
duke@435 | 1008 | |
kamg@2515 | 1009 | // Run error reporting to determine whether or not to report the crash. |
kamg@2515 | 1010 | if (!transmit_report_done && should_report_bug(first_error->_id)) { |
kamg@2515 | 1011 | transmit_report_done = true; |
vlivanov@5027 | 1012 | FILE* hs_err = os::open(log.fd(), "r"); |
kamg@2515 | 1013 | if (NULL != hs_err) { |
kamg@2515 | 1014 | ErrorReporter er; |
kamg@2515 | 1015 | er.call(hs_err, buffer, O_BUFLEN); |
kamg@2515 | 1016 | } |
kamg@2515 | 1017 | } |
kamg@2515 | 1018 | |
duke@435 | 1019 | if (log.fd() != defaultStream::output_fd()) { |
duke@435 | 1020 | close(log.fd()); |
duke@435 | 1021 | } |
duke@435 | 1022 | |
duke@435 | 1023 | log.set_fd(-1); |
duke@435 | 1024 | log_done = true; |
duke@435 | 1025 | } |
duke@435 | 1026 | |
duke@435 | 1027 | |
duke@435 | 1028 | static bool skip_OnError = false; |
duke@435 | 1029 | if (!skip_OnError && OnError && OnError[0]) { |
duke@435 | 1030 | skip_OnError = true; |
duke@435 | 1031 | |
duke@435 | 1032 | out.print_raw_cr("#"); |
duke@435 | 1033 | out.print_raw ("# -XX:OnError=\""); |
duke@435 | 1034 | out.print_raw (OnError); |
duke@435 | 1035 | out.print_raw_cr("\""); |
duke@435 | 1036 | |
duke@435 | 1037 | char* cmd; |
duke@435 | 1038 | const char* ptr = OnError; |
duke@435 | 1039 | while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){ |
duke@435 | 1040 | out.print_raw ("# Executing "); |
never@3156 | 1041 | #if defined(LINUX) || defined(_ALLBSD_SOURCE) |
duke@435 | 1042 | out.print_raw ("/bin/sh -c "); |
duke@435 | 1043 | #elif defined(SOLARIS) |
duke@435 | 1044 | out.print_raw ("/usr/bin/sh -c "); |
duke@435 | 1045 | #endif |
duke@435 | 1046 | out.print_raw ("\""); |
duke@435 | 1047 | out.print_raw (cmd); |
duke@435 | 1048 | out.print_raw_cr("\" ..."); |
duke@435 | 1049 | |
duke@435 | 1050 | os::fork_and_exec(cmd); |
duke@435 | 1051 | } |
duke@435 | 1052 | |
duke@435 | 1053 | // done with OnError |
duke@435 | 1054 | OnError = NULL; |
duke@435 | 1055 | } |
duke@435 | 1056 | |
kvn@6217 | 1057 | static bool skip_replay = ReplayCompiles; // Do not overwrite file during replay |
minqi@4267 | 1058 | if (DumpReplayDataOnError && _thread && _thread->is_Compiler_thread() && !skip_replay) { |
minqi@4267 | 1059 | skip_replay = true; |
minqi@4267 | 1060 | ciEnv* env = ciEnv::current(); |
minqi@4267 | 1061 | if (env != NULL) { |
vlivanov@5027 | 1062 | int fd = prepare_log_file(ReplayDataFile, "replay_pid%p.log", buffer, sizeof(buffer)); |
vlivanov@5027 | 1063 | if (fd != -1) { |
vlivanov@5027 | 1064 | FILE* replay_data_file = os::open(fd, "w"); |
vlivanov@5027 | 1065 | if (replay_data_file != NULL) { |
vlivanov@5027 | 1066 | fileStream replay_data_stream(replay_data_file, /*need_close=*/true); |
vlivanov@5904 | 1067 | env->dump_replay_data_unsafe(&replay_data_stream); |
vlivanov@5027 | 1068 | out.print_raw("#\n# Compiler replay data is saved as:\n# "); |
vlivanov@5027 | 1069 | out.print_raw_cr(buffer); |
vlivanov@5027 | 1070 | } else { |
vlivanov@5027 | 1071 | out.print_raw("#\n# Can't open file to dump replay data. Error: "); |
vlivanov@5027 | 1072 | out.print_raw_cr(strerror(os::get_last_error())); |
vlivanov@5027 | 1073 | } |
vlivanov@5027 | 1074 | } |
minqi@4267 | 1075 | } |
minqi@4267 | 1076 | } |
minqi@4267 | 1077 | |
coleenp@2418 | 1078 | static bool skip_bug_url = !should_report_bug(first_error->_id); |
duke@435 | 1079 | if (!skip_bug_url) { |
duke@435 | 1080 | skip_bug_url = true; |
duke@435 | 1081 | |
duke@435 | 1082 | out.print_raw_cr("#"); |
duke@435 | 1083 | print_bug_submit_message(&out, _thread); |
duke@435 | 1084 | } |
duke@435 | 1085 | |
duke@435 | 1086 | if (!UseOSErrorReporting) { |
duke@435 | 1087 | // os::abort() will call abort hooks, try it first. |
duke@435 | 1088 | static bool skip_os_abort = false; |
duke@435 | 1089 | if (!skip_os_abort) { |
duke@435 | 1090 | skip_os_abort = true; |
coleenp@2418 | 1091 | bool dump_core = should_report_bug(first_error->_id); |
coleenp@2418 | 1092 | os::abort(dump_core); |
duke@435 | 1093 | } |
duke@435 | 1094 | |
duke@435 | 1095 | // if os::abort() doesn't abort, try os::die(); |
duke@435 | 1096 | os::die(); |
duke@435 | 1097 | } |
duke@435 | 1098 | } |
duke@435 | 1099 | |
duke@435 | 1100 | /* |
duke@435 | 1101 | * OnOutOfMemoryError scripts/commands executed while VM is a safepoint - this |
duke@435 | 1102 | * ensures utilities such as jmap can observe the process is a consistent state. |
duke@435 | 1103 | */ |
duke@435 | 1104 | class VM_ReportJavaOutOfMemory : public VM_Operation { |
duke@435 | 1105 | private: |
duke@435 | 1106 | VMError *_err; |
duke@435 | 1107 | public: |
duke@435 | 1108 | VM_ReportJavaOutOfMemory(VMError *err) { _err = err; } |
duke@435 | 1109 | VMOp_Type type() const { return VMOp_ReportJavaOutOfMemory; } |
duke@435 | 1110 | void doit(); |
duke@435 | 1111 | }; |
duke@435 | 1112 | |
duke@435 | 1113 | void VM_ReportJavaOutOfMemory::doit() { |
duke@435 | 1114 | // Don't allocate large buffer on stack |
duke@435 | 1115 | static char buffer[O_BUFLEN]; |
duke@435 | 1116 | |
duke@435 | 1117 | tty->print_cr("#"); |
duke@435 | 1118 | tty->print_cr("# java.lang.OutOfMemoryError: %s", _err->message()); |
duke@435 | 1119 | tty->print_cr("# -XX:OnOutOfMemoryError=\"%s\"", OnOutOfMemoryError); |
duke@435 | 1120 | |
duke@435 | 1121 | // make heap parsability |
duke@435 | 1122 | Universe::heap()->ensure_parsability(false); // no need to retire TLABs |
duke@435 | 1123 | |
duke@435 | 1124 | char* cmd; |
duke@435 | 1125 | const char* ptr = OnOutOfMemoryError; |
duke@435 | 1126 | while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){ |
duke@435 | 1127 | tty->print("# Executing "); |
duke@435 | 1128 | #if defined(LINUX) |
duke@435 | 1129 | tty->print ("/bin/sh -c "); |
duke@435 | 1130 | #elif defined(SOLARIS) |
duke@435 | 1131 | tty->print ("/usr/bin/sh -c "); |
duke@435 | 1132 | #endif |
duke@435 | 1133 | tty->print_cr("\"%s\"...", cmd); |
duke@435 | 1134 | |
duke@435 | 1135 | os::fork_and_exec(cmd); |
duke@435 | 1136 | } |
duke@435 | 1137 | } |
duke@435 | 1138 | |
duke@435 | 1139 | void VMError::report_java_out_of_memory() { |
duke@435 | 1140 | if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { |
duke@435 | 1141 | MutexLocker ml(Heap_lock); |
duke@435 | 1142 | VM_ReportJavaOutOfMemory op(this); |
duke@435 | 1143 | VMThread::execute(&op); |
duke@435 | 1144 | } |
duke@435 | 1145 | } |