| 1 | /* |
| 2 | * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 12 | * version 2 for more details (a copy is included in the LICENSE file that |
| 13 | * accompanied this code). |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License version |
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | * |
| 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| 20 | * or visit www.oracle.com if you need additional information or have any |
| 21 | * questions. |
| 22 | * |
| 23 | */ |
| 24 | |
| 25 | #include "precompiled.hpp" |
| 26 | #include "classfile/systemDictionary.hpp" |
| 27 | #include "classfile/vmSymbols.hpp" |
| 28 | #include "compiler/compileBroker.hpp" |
| 29 | #include "logging/log.hpp" |
| 30 | #include "logging/logStream.hpp" |
| 31 | #include "memory/resourceArea.hpp" |
| 32 | #include "memory/universe.hpp" |
| 33 | #include "oops/oop.inline.hpp" |
| 34 | #include "runtime/handles.inline.hpp" |
| 35 | #include "runtime/init.hpp" |
| 36 | #include "runtime/java.hpp" |
| 37 | #include "runtime/javaCalls.hpp" |
| 38 | #include "runtime/os.hpp" |
| 39 | #include "runtime/thread.inline.hpp" |
| 40 | #include "runtime/threadCritical.hpp" |
| 41 | #include "runtime/atomic.hpp" |
| 42 | #include "utilities/events.hpp" |
| 43 | #include "utilities/exceptions.hpp" |
| 44 | |
| 45 | // Implementation of ThreadShadow |
| 46 | void check_ThreadShadow() { |
| 47 | const ByteSize offset1 = byte_offset_of(ThreadShadow, _pending_exception); |
| 48 | const ByteSize offset2 = Thread::pending_exception_offset(); |
| 49 | if (offset1 != offset2) fatal("ThreadShadow::_pending_exception is not positioned correctly" ); |
| 50 | } |
| 51 | |
| 52 | |
| 53 | void ThreadShadow::set_pending_exception(oop exception, const char* file, int line) { |
| 54 | assert(exception != NULL && oopDesc::is_oop(exception), "invalid exception oop" ); |
| 55 | _pending_exception = exception; |
| 56 | _exception_file = file; |
| 57 | _exception_line = line; |
| 58 | } |
| 59 | |
| 60 | void ThreadShadow::clear_pending_exception() { |
| 61 | LogTarget(Debug, exceptions) lt; |
| 62 | if (_pending_exception != NULL && lt.is_enabled()) { |
| 63 | ResourceMark rm; |
| 64 | LogStream ls(lt); |
| 65 | ls.print("Thread::clear_pending_exception: cleared exception:" ); |
| 66 | _pending_exception->print_on(&ls); |
| 67 | } |
| 68 | _pending_exception = NULL; |
| 69 | _exception_file = NULL; |
| 70 | _exception_line = 0; |
| 71 | } |
| 72 | // Implementation of Exceptions |
| 73 | |
| 74 | bool Exceptions::special_exception(Thread* thread, const char* file, int line, Handle h_exception) { |
| 75 | // bootstrapping check |
| 76 | if (!Universe::is_fully_initialized()) { |
| 77 | vm_exit_during_initialization(h_exception); |
| 78 | ShouldNotReachHere(); |
| 79 | } |
| 80 | |
| 81 | #ifdef ASSERT |
| 82 | // Check for trying to throw stack overflow before initialization is complete |
| 83 | // to prevent infinite recursion trying to initialize stack overflow without |
| 84 | // adequate stack space. |
| 85 | // This can happen with stress testing a large value of StackShadowPages |
| 86 | if (h_exception()->klass() == SystemDictionary::StackOverflowError_klass()) { |
| 87 | InstanceKlass* ik = InstanceKlass::cast(h_exception->klass()); |
| 88 | assert(ik->is_initialized(), |
| 89 | "need to increase java_thread_min_stack_allowed calculation" ); |
| 90 | } |
| 91 | #endif // ASSERT |
| 92 | |
| 93 | if (thread->is_VM_thread() |
| 94 | || !thread->can_call_java()) { |
| 95 | // We do not care what kind of exception we get for the vm-thread or a thread which |
| 96 | // is compiling. We just install a dummy exception object |
| 97 | thread->set_pending_exception(Universe::vm_exception(), file, line); |
| 98 | return true; |
| 99 | } |
| 100 | |
| 101 | return false; |
| 102 | } |
| 103 | |
| 104 | bool Exceptions::special_exception(Thread* thread, const char* file, int line, Symbol* h_name, const char* message) { |
| 105 | // bootstrapping check |
| 106 | if (!Universe::is_fully_initialized()) { |
| 107 | if (h_name == NULL) { |
| 108 | // atleast an informative message. |
| 109 | vm_exit_during_initialization("Exception" , message); |
| 110 | } else { |
| 111 | vm_exit_during_initialization(h_name, message); |
| 112 | } |
| 113 | ShouldNotReachHere(); |
| 114 | } |
| 115 | |
| 116 | if (thread->is_VM_thread() |
| 117 | || !thread->can_call_java()) { |
| 118 | // We do not care what kind of exception we get for the vm-thread or a thread which |
| 119 | // is compiling. We just install a dummy exception object |
| 120 | thread->set_pending_exception(Universe::vm_exception(), file, line); |
| 121 | return true; |
| 122 | } |
| 123 | return false; |
| 124 | } |
| 125 | |
| 126 | // This method should only be called from generated code, |
| 127 | // therefore the exception oop should be in the oopmap. |
| 128 | void Exceptions::_throw_oop(Thread* thread, const char* file, int line, oop exception) { |
| 129 | assert(exception != NULL, "exception should not be NULL" ); |
| 130 | Handle h_exception(thread, exception); |
| 131 | _throw(thread, file, line, h_exception); |
| 132 | } |
| 133 | |
| 134 | void Exceptions::_throw(Thread* thread, const char* file, int line, Handle h_exception, const char* message) { |
| 135 | ResourceMark rm(thread); |
| 136 | assert(h_exception() != NULL, "exception should not be NULL" ); |
| 137 | |
| 138 | // tracing (do this up front - so it works during boot strapping) |
| 139 | // Note, the print_value_string() argument is not called unless logging is enabled! |
| 140 | log_info(exceptions)("Exception <%s%s%s> (" INTPTR_FORMAT ") \n" |
| 141 | "thrown [%s, line %d]\nfor thread " INTPTR_FORMAT, |
| 142 | h_exception->print_value_string(), |
| 143 | message ? ": " : "" , message ? message : "" , |
| 144 | p2i(h_exception()), file, line, p2i(thread)); |
| 145 | |
| 146 | // for AbortVMOnException flag |
| 147 | Exceptions::debug_check_abort(h_exception, message); |
| 148 | |
| 149 | // Check for special boot-strapping/vm-thread handling |
| 150 | if (special_exception(thread, file, line, h_exception)) { |
| 151 | return; |
| 152 | } |
| 153 | |
| 154 | if (h_exception->is_a(SystemDictionary::OutOfMemoryError_klass())) { |
| 155 | count_out_of_memory_exceptions(h_exception); |
| 156 | } |
| 157 | |
| 158 | if (h_exception->is_a(SystemDictionary::LinkageError_klass())) { |
| 159 | Atomic::inc(&_linkage_errors); |
| 160 | } |
| 161 | |
| 162 | assert(h_exception->is_a(SystemDictionary::Throwable_klass()), "exception is not a subclass of java/lang/Throwable" ); |
| 163 | |
| 164 | // set the pending exception |
| 165 | thread->set_pending_exception(h_exception(), file, line); |
| 166 | |
| 167 | // vm log |
| 168 | Events::log_exception(thread, h_exception, message, file, line); |
| 169 | } |
| 170 | |
| 171 | |
| 172 | void Exceptions::_throw_msg(Thread* thread, const char* file, int line, Symbol* name, const char* message, |
| 173 | Handle h_loader, Handle h_protection_domain) { |
| 174 | // Check for special boot-strapping/vm-thread handling |
| 175 | if (special_exception(thread, file, line, name, message)) return; |
| 176 | // Create and throw exception |
| 177 | Handle h_cause(thread, NULL); |
| 178 | Handle h_exception = new_exception(thread, name, message, h_cause, h_loader, h_protection_domain); |
| 179 | _throw(thread, file, line, h_exception, message); |
| 180 | } |
| 181 | |
| 182 | void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause, |
| 183 | Handle h_loader, Handle h_protection_domain) { |
| 184 | // Check for special boot-strapping/vm-thread handling |
| 185 | if (special_exception(thread, file, line, name, message)) return; |
| 186 | // Create and throw exception and init cause |
| 187 | Handle h_exception = new_exception(thread, name, message, h_cause, h_loader, h_protection_domain); |
| 188 | _throw(thread, file, line, h_exception, message); |
| 189 | } |
| 190 | |
| 191 | void Exceptions::_throw_cause(Thread* thread, const char* file, int line, Symbol* name, Handle h_cause, |
| 192 | Handle h_loader, Handle h_protection_domain) { |
| 193 | // Check for special boot-strapping/vm-thread handling |
| 194 | if (special_exception(thread, file, line, h_cause)) return; |
| 195 | // Create and throw exception |
| 196 | Handle h_exception = new_exception(thread, name, h_cause, h_loader, h_protection_domain); |
| 197 | _throw(thread, file, line, h_exception, NULL); |
| 198 | } |
| 199 | |
| 200 | void Exceptions::_throw_args(Thread* thread, const char* file, int line, Symbol* name, Symbol* signature, JavaCallArguments *args) { |
| 201 | // Check for special boot-strapping/vm-thread handling |
| 202 | if (special_exception(thread, file, line, name, NULL)) return; |
| 203 | // Create and throw exception |
| 204 | Handle h_loader(thread, NULL); |
| 205 | Handle h_prot(thread, NULL); |
| 206 | Handle exception = new_exception(thread, name, signature, args, h_loader, h_prot); |
| 207 | _throw(thread, file, line, exception); |
| 208 | } |
| 209 | |
| 210 | |
| 211 | // Methods for default parameters. |
| 212 | // NOTE: These must be here (and not in the header file) because of include circularities. |
| 213 | void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause) { |
| 214 | _throw_msg_cause(thread, file, line, name, message, h_cause, Handle(thread, NULL), Handle(thread, NULL)); |
| 215 | } |
| 216 | void Exceptions::_throw_msg(Thread* thread, const char* file, int line, Symbol* name, const char* message) { |
| 217 | _throw_msg(thread, file, line, name, message, Handle(thread, NULL), Handle(thread, NULL)); |
| 218 | } |
| 219 | void Exceptions::_throw_cause(Thread* thread, const char* file, int line, Symbol* name, Handle h_cause) { |
| 220 | _throw_cause(thread, file, line, name, h_cause, Handle(thread, NULL), Handle(thread, NULL)); |
| 221 | } |
| 222 | |
| 223 | |
| 224 | void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line, const methodHandle& method) { |
| 225 | Handle exception; |
| 226 | if (!THREAD->has_pending_exception()) { |
| 227 | InstanceKlass* k = SystemDictionary::StackOverflowError_klass(); |
| 228 | oop e = k->allocate_instance(CHECK); |
| 229 | exception = Handle(THREAD, e); // fill_in_stack trace does gc |
| 230 | assert(k->is_initialized(), "need to increase java_thread_min_stack_allowed calculation" ); |
| 231 | if (StackTraceInThrowable) { |
| 232 | java_lang_Throwable::fill_in_stack_trace(exception, method()); |
| 233 | } |
| 234 | // Increment counter for hs_err file reporting |
| 235 | Atomic::inc(&Exceptions::_stack_overflow_errors); |
| 236 | } else { |
| 237 | // if prior exception, throw that one instead |
| 238 | exception = Handle(THREAD, THREAD->pending_exception()); |
| 239 | } |
| 240 | _throw(THREAD, file, line, exception); |
| 241 | } |
| 242 | |
| 243 | void Exceptions::fthrow(Thread* thread, const char* file, int line, Symbol* h_name, const char* format, ...) { |
| 244 | const int max_msg_size = 1024; |
| 245 | va_list ap; |
| 246 | va_start(ap, format); |
| 247 | char msg[max_msg_size]; |
| 248 | os::vsnprintf(msg, max_msg_size, format, ap); |
| 249 | va_end(ap); |
| 250 | _throw_msg(thread, file, line, h_name, msg); |
| 251 | } |
| 252 | |
| 253 | |
| 254 | // Creates an exception oop, calls the <init> method with the given signature. |
| 255 | // and returns a Handle |
| 256 | Handle Exceptions::new_exception(Thread *thread, Symbol* name, |
| 257 | Symbol* signature, JavaCallArguments *args, |
| 258 | Handle h_loader, Handle h_protection_domain) { |
| 259 | assert(Universe::is_fully_initialized(), |
| 260 | "cannot be called during initialization" ); |
| 261 | assert(thread->is_Java_thread(), "can only be called by a Java thread" ); |
| 262 | assert(!thread->has_pending_exception(), "already has exception" ); |
| 263 | |
| 264 | Handle h_exception; |
| 265 | |
| 266 | // Resolve exception klass, and check for pending exception below. |
| 267 | Klass* klass = SystemDictionary::resolve_or_fail(name, h_loader, h_protection_domain, true, thread); |
| 268 | |
| 269 | if (!thread->has_pending_exception()) { |
| 270 | assert(klass != NULL, "klass must exist" ); |
| 271 | h_exception = JavaCalls::construct_new_instance(InstanceKlass::cast(klass), |
| 272 | signature, |
| 273 | args, |
| 274 | thread); |
| 275 | } |
| 276 | |
| 277 | // Check if another exception was thrown in the process, if so rethrow that one |
| 278 | if (thread->has_pending_exception()) { |
| 279 | h_exception = Handle(thread, thread->pending_exception()); |
| 280 | thread->clear_pending_exception(); |
| 281 | } |
| 282 | return h_exception; |
| 283 | } |
| 284 | |
| 285 | // Creates an exception oop, calls the <init> method with the given signature. |
| 286 | // and returns a Handle |
| 287 | // Initializes the cause if cause non-null |
| 288 | Handle Exceptions::new_exception(Thread *thread, Symbol* name, |
| 289 | Symbol* signature, JavaCallArguments *args, |
| 290 | Handle h_cause, |
| 291 | Handle h_loader, Handle h_protection_domain) { |
| 292 | Handle h_exception = new_exception(thread, name, signature, args, h_loader, h_protection_domain); |
| 293 | |
| 294 | // Future: object initializer should take a cause argument |
| 295 | if (h_cause.not_null()) { |
| 296 | assert(h_cause->is_a(SystemDictionary::Throwable_klass()), |
| 297 | "exception cause is not a subclass of java/lang/Throwable" ); |
| 298 | JavaValue result1(T_OBJECT); |
| 299 | JavaCallArguments args1; |
| 300 | args1.set_receiver(h_exception); |
| 301 | args1.push_oop(h_cause); |
| 302 | JavaCalls::call_virtual(&result1, h_exception->klass(), |
| 303 | vmSymbols::initCause_name(), |
| 304 | vmSymbols::throwable_throwable_signature(), |
| 305 | &args1, |
| 306 | thread); |
| 307 | } |
| 308 | |
| 309 | // Check if another exception was thrown in the process, if so rethrow that one |
| 310 | if (thread->has_pending_exception()) { |
| 311 | h_exception = Handle(thread, thread->pending_exception()); |
| 312 | thread->clear_pending_exception(); |
| 313 | } |
| 314 | return h_exception; |
| 315 | } |
| 316 | |
| 317 | // Convenience method. Calls either the <init>() or <init>(Throwable) method when |
| 318 | // creating a new exception |
| 319 | Handle Exceptions::new_exception(Thread* thread, Symbol* name, |
| 320 | Handle h_cause, |
| 321 | Handle h_loader, Handle h_protection_domain, |
| 322 | ExceptionMsgToUtf8Mode to_utf8_safe) { |
| 323 | JavaCallArguments args; |
| 324 | Symbol* signature = NULL; |
| 325 | if (h_cause.is_null()) { |
| 326 | signature = vmSymbols::void_method_signature(); |
| 327 | } else { |
| 328 | signature = vmSymbols::throwable_void_signature(); |
| 329 | args.push_oop(h_cause); |
| 330 | } |
| 331 | return new_exception(thread, name, signature, &args, h_loader, h_protection_domain); |
| 332 | } |
| 333 | |
| 334 | // Convenience method. Calls either the <init>() or <init>(String) method when |
| 335 | // creating a new exception |
| 336 | Handle Exceptions::new_exception(Thread* thread, Symbol* name, |
| 337 | const char* message, Handle h_cause, |
| 338 | Handle h_loader, Handle h_protection_domain, |
| 339 | ExceptionMsgToUtf8Mode to_utf8_safe) { |
| 340 | JavaCallArguments args; |
| 341 | Symbol* signature = NULL; |
| 342 | if (message == NULL) { |
| 343 | signature = vmSymbols::void_method_signature(); |
| 344 | } else { |
| 345 | // We want to allocate storage, but we can't do that if there's |
| 346 | // a pending exception, so we preserve any pending exception |
| 347 | // around the allocation. |
| 348 | // If we get an exception from the allocation, prefer that to |
| 349 | // the exception we are trying to build, or the pending exception. |
| 350 | // This is sort of like what PRESERVE_EXCEPTION_MARK does, except |
| 351 | // for the preferencing and the early returns. |
| 352 | Handle incoming_exception(thread, NULL); |
| 353 | if (thread->has_pending_exception()) { |
| 354 | incoming_exception = Handle(thread, thread->pending_exception()); |
| 355 | thread->clear_pending_exception(); |
| 356 | } |
| 357 | Handle msg; |
| 358 | if (to_utf8_safe == safe_to_utf8) { |
| 359 | // Make a java UTF8 string. |
| 360 | msg = java_lang_String::create_from_str(message, thread); |
| 361 | } else { |
| 362 | // Make a java string keeping the encoding scheme of the original string. |
| 363 | msg = java_lang_String::create_from_platform_dependent_str(message, thread); |
| 364 | } |
| 365 | if (thread->has_pending_exception()) { |
| 366 | Handle exception(thread, thread->pending_exception()); |
| 367 | thread->clear_pending_exception(); |
| 368 | return exception; |
| 369 | } |
| 370 | if (incoming_exception.not_null()) { |
| 371 | return incoming_exception; |
| 372 | } |
| 373 | args.push_oop(msg); |
| 374 | signature = vmSymbols::string_void_signature(); |
| 375 | } |
| 376 | return new_exception(thread, name, signature, &args, h_cause, h_loader, h_protection_domain); |
| 377 | } |
| 378 | |
| 379 | // Another convenience method that creates handles for null class loaders and |
| 380 | // protection domains and null causes. |
| 381 | // If the last parameter 'to_utf8_mode' is safe_to_utf8, |
| 382 | // it means we can safely ignore the encoding scheme of the message string and |
| 383 | // convert it directly to a java UTF8 string. Otherwise, we need to take the |
| 384 | // encoding scheme of the string into account. One thing we should do at some |
| 385 | // point is to push this flag down to class java_lang_String since other |
| 386 | // classes may need similar functionalities. |
| 387 | Handle Exceptions::new_exception(Thread* thread, Symbol* name, |
| 388 | const char* message, |
| 389 | ExceptionMsgToUtf8Mode to_utf8_safe) { |
| 390 | |
| 391 | Handle h_loader(thread, NULL); |
| 392 | Handle h_prot(thread, NULL); |
| 393 | Handle h_cause(thread, NULL); |
| 394 | return Exceptions::new_exception(thread, name, message, h_cause, h_loader, |
| 395 | h_prot, to_utf8_safe); |
| 396 | } |
| 397 | |
| 398 | // invokedynamic uses wrap_dynamic_exception for: |
| 399 | // - bootstrap method resolution |
| 400 | // - post call to MethodHandleNatives::linkCallSite |
| 401 | // dynamically computed constant uses wrap_dynamic_exception for: |
| 402 | // - bootstrap method resolution |
| 403 | // - post call to MethodHandleNatives::linkDynamicConstant |
| 404 | void Exceptions::wrap_dynamic_exception(Thread* THREAD) { |
| 405 | if (THREAD->has_pending_exception()) { |
| 406 | oop exception = THREAD->pending_exception(); |
| 407 | // See the "Linking Exceptions" section for the invokedynamic instruction |
| 408 | // in JVMS 6.5. |
| 409 | if (exception->is_a(SystemDictionary::Error_klass())) { |
| 410 | // Pass through an Error, including BootstrapMethodError, any other form |
| 411 | // of linkage error, or say ThreadDeath/OutOfMemoryError |
| 412 | if (TraceMethodHandles) { |
| 413 | tty->print_cr("bootstrap method invocation wraps BSME around " INTPTR_FORMAT, p2i((void *)exception)); |
| 414 | exception->print(); |
| 415 | } |
| 416 | return; |
| 417 | } |
| 418 | |
| 419 | // Otherwise wrap the exception in a BootstrapMethodError |
| 420 | if (TraceMethodHandles) { |
| 421 | tty->print_cr("[constant/invoke]dynamic throws BSME for " INTPTR_FORMAT, p2i((void *)exception)); |
| 422 | exception->print(); |
| 423 | } |
| 424 | Handle nested_exception(THREAD, exception); |
| 425 | THREAD->clear_pending_exception(); |
| 426 | THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception) |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | // Exception counting for hs_err file |
| 431 | volatile int Exceptions::_stack_overflow_errors = 0; |
| 432 | volatile int Exceptions::_linkage_errors = 0; |
| 433 | volatile int Exceptions::_out_of_memory_error_java_heap_errors = 0; |
| 434 | volatile int Exceptions::_out_of_memory_error_metaspace_errors = 0; |
| 435 | volatile int Exceptions::_out_of_memory_error_class_metaspace_errors = 0; |
| 436 | |
| 437 | void Exceptions::count_out_of_memory_exceptions(Handle exception) { |
| 438 | if (oopDesc::equals(exception(), Universe::out_of_memory_error_metaspace())) { |
| 439 | Atomic::inc(&_out_of_memory_error_metaspace_errors); |
| 440 | } else if (oopDesc::equals(exception(), Universe::out_of_memory_error_class_metaspace())) { |
| 441 | Atomic::inc(&_out_of_memory_error_class_metaspace_errors); |
| 442 | } else { |
| 443 | // everything else reported as java heap OOM |
| 444 | Atomic::inc(&_out_of_memory_error_java_heap_errors); |
| 445 | } |
| 446 | } |
| 447 | |
| 448 | void print_oom_count(outputStream* st, const char *err, int count) { |
| 449 | if (count > 0) { |
| 450 | st->print_cr("OutOfMemoryError %s=%d" , err, count); |
| 451 | } |
| 452 | } |
| 453 | |
| 454 | bool Exceptions::has_exception_counts() { |
| 455 | return (_stack_overflow_errors + _out_of_memory_error_java_heap_errors + |
| 456 | _out_of_memory_error_metaspace_errors + _out_of_memory_error_class_metaspace_errors) > 0; |
| 457 | } |
| 458 | |
| 459 | void Exceptions::print_exception_counts_on_error(outputStream* st) { |
| 460 | print_oom_count(st, "java_heap_errors" , _out_of_memory_error_java_heap_errors); |
| 461 | print_oom_count(st, "metaspace_errors" , _out_of_memory_error_metaspace_errors); |
| 462 | print_oom_count(st, "class_metaspace_errors" , _out_of_memory_error_class_metaspace_errors); |
| 463 | if (_stack_overflow_errors > 0) { |
| 464 | st->print_cr("StackOverflowErrors=%d" , _stack_overflow_errors); |
| 465 | } |
| 466 | if (_linkage_errors > 0) { |
| 467 | st->print_cr("LinkageErrors=%d" , _linkage_errors); |
| 468 | } |
| 469 | } |
| 470 | |
| 471 | // Implementation of ExceptionMark |
| 472 | |
| 473 | ExceptionMark::ExceptionMark(Thread*& thread) { |
| 474 | thread = Thread::current(); |
| 475 | _thread = thread; |
| 476 | if (_thread->has_pending_exception()) { |
| 477 | oop exception = _thread->pending_exception(); |
| 478 | _thread->clear_pending_exception(); // Needed to avoid infinite recursion |
| 479 | exception->print(); |
| 480 | fatal("ExceptionMark constructor expects no pending exceptions" ); |
| 481 | } |
| 482 | } |
| 483 | |
| 484 | |
| 485 | ExceptionMark::~ExceptionMark() { |
| 486 | if (_thread->has_pending_exception()) { |
| 487 | Handle exception(_thread, _thread->pending_exception()); |
| 488 | _thread->clear_pending_exception(); // Needed to avoid infinite recursion |
| 489 | if (is_init_completed()) { |
| 490 | exception->print(); |
| 491 | fatal("ExceptionMark destructor expects no pending exceptions" ); |
| 492 | } else { |
| 493 | vm_exit_during_initialization(exception); |
| 494 | } |
| 495 | } |
| 496 | } |
| 497 | |
| 498 | // ---------------------------------------------------------------------------------------- |
| 499 | |
| 500 | // caller frees value_string if necessary |
| 501 | void Exceptions::debug_check_abort(const char *value_string, const char* message) { |
| 502 | if (AbortVMOnException != NULL && value_string != NULL && |
| 503 | strstr(value_string, AbortVMOnException)) { |
| 504 | if (AbortVMOnExceptionMessage == NULL || (message != NULL && |
| 505 | strstr(message, AbortVMOnExceptionMessage))) { |
| 506 | fatal("Saw %s, aborting" , value_string); |
| 507 | } |
| 508 | } |
| 509 | } |
| 510 | |
| 511 | void Exceptions::debug_check_abort(Handle exception, const char* message) { |
| 512 | if (AbortVMOnException != NULL) { |
| 513 | debug_check_abort_helper(exception, message); |
| 514 | } |
| 515 | } |
| 516 | |
| 517 | void Exceptions::debug_check_abort_helper(Handle exception, const char* message) { |
| 518 | ResourceMark rm; |
| 519 | if (message == NULL && exception->is_a(SystemDictionary::Throwable_klass())) { |
| 520 | oop msg = java_lang_Throwable::message(exception()); |
| 521 | if (msg != NULL) { |
| 522 | message = java_lang_String::as_utf8_string(msg); |
| 523 | } |
| 524 | } |
| 525 | debug_check_abort(exception()->klass()->external_name(), message); |
| 526 | } |
| 527 | |
| 528 | // for logging exceptions |
| 529 | void Exceptions::log_exception(Handle exception, const char* message) { |
| 530 | ResourceMark rm; |
| 531 | Symbol* detail_message = java_lang_Throwable::detail_message(exception()); |
| 532 | if (detail_message != NULL) { |
| 533 | log_info(exceptions)("Exception <%s: %s>\n thrown in %s" , |
| 534 | exception->print_value_string(), |
| 535 | detail_message->as_C_string(), |
| 536 | message); |
| 537 | } else { |
| 538 | log_info(exceptions)("Exception <%s>\n thrown in %s" , |
| 539 | exception->print_value_string(), |
| 540 | message); |
| 541 | } |
| 542 | } |
| 543 | |