src/share/vm/utilities/exceptions.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/utilities/exceptions.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,452 @@
     1.4 +/*
     1.5 + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "classfile/systemDictionary.hpp"
    1.30 +#include "classfile/vmSymbols.hpp"
    1.31 +#include "compiler/compileBroker.hpp"
    1.32 +#include "oops/oop.inline.hpp"
    1.33 +#include "runtime/init.hpp"
    1.34 +#include "runtime/java.hpp"
    1.35 +#include "runtime/javaCalls.hpp"
    1.36 +#include "runtime/thread.inline.hpp"
    1.37 +#include "runtime/threadCritical.hpp"
    1.38 +#include "utilities/events.hpp"
    1.39 +#include "utilities/exceptions.hpp"
    1.40 +
    1.41 +PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
    1.42 +
    1.43 +// Implementation of ThreadShadow
    1.44 +void check_ThreadShadow() {
    1.45 +  const ByteSize offset1 = byte_offset_of(ThreadShadow, _pending_exception);
    1.46 +  const ByteSize offset2 = Thread::pending_exception_offset();
    1.47 +  if (offset1 != offset2) fatal("ThreadShadow::_pending_exception is not positioned correctly");
    1.48 +}
    1.49 +
    1.50 +
    1.51 +void ThreadShadow::set_pending_exception(oop exception, const char* file, int line) {
    1.52 +  assert(exception != NULL && exception->is_oop(), "invalid exception oop");
    1.53 +  _pending_exception = exception;
    1.54 +  _exception_file    = file;
    1.55 +  _exception_line    = line;
    1.56 +}
    1.57 +
    1.58 +void ThreadShadow::clear_pending_exception() {
    1.59 +  if (TraceClearedExceptions) {
    1.60 +    if (_pending_exception != NULL) {
    1.61 +      tty->print_cr("Thread::clear_pending_exception: cleared exception:");
    1.62 +      _pending_exception->print();
    1.63 +    }
    1.64 +  }
    1.65 +  _pending_exception = NULL;
    1.66 +  _exception_file    = NULL;
    1.67 +  _exception_line    = 0;
    1.68 +}
    1.69 +// Implementation of Exceptions
    1.70 +
    1.71 +bool Exceptions::special_exception(Thread* thread, const char* file, int line, Handle h_exception) {
    1.72 +  // bootstrapping check
    1.73 +  if (!Universe::is_fully_initialized()) {
    1.74 +   vm_exit_during_initialization(h_exception);
    1.75 +   ShouldNotReachHere();
    1.76 +  }
    1.77 +
    1.78 +#ifdef ASSERT
    1.79 +  // Check for trying to throw stack overflow before initialization is complete
    1.80 +  // to prevent infinite recursion trying to initialize stack overflow without
    1.81 +  // adequate stack space.
    1.82 +  // This can happen with stress testing a large value of StackShadowPages
    1.83 +  if (h_exception()->klass() == SystemDictionary::StackOverflowError_klass()) {
    1.84 +    InstanceKlass* ik = InstanceKlass::cast(h_exception->klass());
    1.85 +    assert(ik->is_initialized(),
    1.86 +           "need to increase min_stack_allowed calculation");
    1.87 +  }
    1.88 +#endif // ASSERT
    1.89 +
    1.90 +  if (thread->is_VM_thread()
    1.91 +      || thread->is_Compiler_thread() ) {
    1.92 +    // We do not care what kind of exception we get for the vm-thread or a thread which
    1.93 +    // is compiling.  We just install a dummy exception object
    1.94 +    thread->set_pending_exception(Universe::vm_exception(), file, line);
    1.95 +    return true;
    1.96 +  }
    1.97 +
    1.98 +  return false;
    1.99 +}
   1.100 +
   1.101 +bool Exceptions::special_exception(Thread* thread, const char* file, int line, Symbol* h_name, const char* message) {
   1.102 +  // bootstrapping check
   1.103 +  if (!Universe::is_fully_initialized()) {
   1.104 +    if (h_name == NULL) {
   1.105 +      // atleast an informative message.
   1.106 +      vm_exit_during_initialization("Exception", message);
   1.107 +    } else {
   1.108 +      vm_exit_during_initialization(h_name, message);
   1.109 +    }
   1.110 +    ShouldNotReachHere();
   1.111 +  }
   1.112 +
   1.113 +  if (thread->is_VM_thread()
   1.114 +      || thread->is_Compiler_thread() ) {
   1.115 +    // We do not care what kind of exception we get for the vm-thread or a thread which
   1.116 +    // is compiling.  We just install a dummy exception object
   1.117 +    thread->set_pending_exception(Universe::vm_exception(), file, line);
   1.118 +    return true;
   1.119 +  }
   1.120 +  return false;
   1.121 +}
   1.122 +
   1.123 +// This method should only be called from generated code,
   1.124 +// therefore the exception oop should be in the oopmap.
   1.125 +void Exceptions::_throw_oop(Thread* thread, const char* file, int line, oop exception) {
   1.126 +  assert(exception != NULL, "exception should not be NULL");
   1.127 +  Handle h_exception = Handle(thread, exception);
   1.128 +  _throw(thread, file, line, h_exception);
   1.129 +}
   1.130 +
   1.131 +void Exceptions::_throw(Thread* thread, const char* file, int line, Handle h_exception, const char* message) {
   1.132 +  ResourceMark rm;
   1.133 +  assert(h_exception() != NULL, "exception should not be NULL");
   1.134 +
   1.135 +  // tracing (do this up front - so it works during boot strapping)
   1.136 +  if (TraceExceptions) {
   1.137 +    ttyLocker ttyl;
   1.138 +    tty->print_cr("Exception <%s%s%s> (" INTPTR_FORMAT ") \n"
   1.139 +                  "thrown [%s, line %d]\nfor thread " INTPTR_FORMAT,
   1.140 +                  h_exception->print_value_string(),
   1.141 +                  message ? ": " : "", message ? message : "",
   1.142 +                  (address)h_exception(), file, line, thread);
   1.143 +  }
   1.144 +  // for AbortVMOnException flag
   1.145 +  NOT_PRODUCT(Exceptions::debug_check_abort(h_exception, message));
   1.146 +
   1.147 +  // Check for special boot-strapping/vm-thread handling
   1.148 +  if (special_exception(thread, file, line, h_exception)) {
   1.149 +    return;
   1.150 +  }
   1.151 +
   1.152 +  assert(h_exception->is_a(SystemDictionary::Throwable_klass()), "exception is not a subclass of java/lang/Throwable");
   1.153 +
   1.154 +  // set the pending exception
   1.155 +  thread->set_pending_exception(h_exception(), file, line);
   1.156 +
   1.157 +  // vm log
   1.158 +  Events::log_exception(thread, "Exception <%s%s%s> (" INTPTR_FORMAT ") thrown at [%s, line %d]",
   1.159 +                        h_exception->print_value_string(), message ? ": " : "", message ? message : "",
   1.160 +                        (address)h_exception(), file, line);
   1.161 +}
   1.162 +
   1.163 +
   1.164 +void Exceptions::_throw_msg(Thread* thread, const char* file, int line, Symbol* name, const char* message,
   1.165 +                            Handle h_loader, Handle h_protection_domain) {
   1.166 +  // Check for special boot-strapping/vm-thread handling
   1.167 +  if (special_exception(thread, file, line, name, message)) return;
   1.168 +  // Create and throw exception
   1.169 +  Handle h_cause(thread, NULL);
   1.170 +  Handle h_exception = new_exception(thread, name, message, h_cause, h_loader, h_protection_domain);
   1.171 +  _throw(thread, file, line, h_exception, message);
   1.172 +}
   1.173 +
   1.174 +void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause,
   1.175 +                                  Handle h_loader, Handle h_protection_domain) {
   1.176 +  // Check for special boot-strapping/vm-thread handling
   1.177 +  if (special_exception(thread, file, line, name, message)) return;
   1.178 +  // Create and throw exception and init cause
   1.179 +  Handle h_exception = new_exception(thread, name, message, h_cause, h_loader, h_protection_domain);
   1.180 +  _throw(thread, file, line, h_exception, message);
   1.181 +}
   1.182 +
   1.183 +void Exceptions::_throw_cause(Thread* thread, const char* file, int line, Symbol* name, Handle h_cause,
   1.184 +                              Handle h_loader, Handle h_protection_domain) {
   1.185 +  // Check for special boot-strapping/vm-thread handling
   1.186 +  if (special_exception(thread, file, line, h_cause)) return;
   1.187 +  // Create and throw exception
   1.188 +  Handle h_exception = new_exception(thread, name, h_cause, h_loader, h_protection_domain);
   1.189 +  _throw(thread, file, line, h_exception, NULL);
   1.190 +}
   1.191 +
   1.192 +void Exceptions::_throw_args(Thread* thread, const char* file, int line, Symbol* name, Symbol* signature, JavaCallArguments *args) {
   1.193 +  // Check for special boot-strapping/vm-thread handling
   1.194 +  if (special_exception(thread, file, line, name, NULL)) return;
   1.195 +  // Create and throw exception
   1.196 +  Handle h_loader(thread, NULL);
   1.197 +  Handle h_prot(thread, NULL);
   1.198 +  Handle exception = new_exception(thread, name, signature, args, h_loader, h_prot);
   1.199 +  _throw(thread, file, line, exception);
   1.200 +}
   1.201 +
   1.202 +
   1.203 +// Methods for default parameters.
   1.204 +// NOTE: These must be here (and not in the header file) because of include circularities.
   1.205 +void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause) {
   1.206 +  _throw_msg_cause(thread, file, line, name, message, h_cause, Handle(thread, NULL), Handle(thread, NULL));
   1.207 +}
   1.208 +void Exceptions::_throw_msg(Thread* thread, const char* file, int line, Symbol* name, const char* message) {
   1.209 +  _throw_msg(thread, file, line, name, message, Handle(thread, NULL), Handle(thread, NULL));
   1.210 +}
   1.211 +void Exceptions::_throw_cause(Thread* thread, const char* file, int line, Symbol* name, Handle h_cause) {
   1.212 +  _throw_cause(thread, file, line, name, h_cause, Handle(thread, NULL), Handle(thread, NULL));
   1.213 +}
   1.214 +
   1.215 +
   1.216 +void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line, methodHandle method) {
   1.217 +  Handle exception;
   1.218 +  if (!THREAD->has_pending_exception()) {
   1.219 +    Klass* k = SystemDictionary::StackOverflowError_klass();
   1.220 +    oop e = InstanceKlass::cast(k)->allocate_instance(CHECK);
   1.221 +    exception = Handle(THREAD, e);  // fill_in_stack trace does gc
   1.222 +    assert(InstanceKlass::cast(k)->is_initialized(), "need to increase min_stack_allowed calculation");
   1.223 +    if (StackTraceInThrowable) {
   1.224 +      java_lang_Throwable::fill_in_stack_trace(exception, method());
   1.225 +    }
   1.226 +  } else {
   1.227 +    // if prior exception, throw that one instead
   1.228 +    exception = Handle(THREAD, THREAD->pending_exception());
   1.229 +  }
   1.230 +  _throw(THREAD, file, line, exception);
   1.231 +}
   1.232 +
   1.233 +void Exceptions::fthrow(Thread* thread, const char* file, int line, Symbol* h_name, const char* format, ...) {
   1.234 +  const int max_msg_size = 1024;
   1.235 +  va_list ap;
   1.236 +  va_start(ap, format);
   1.237 +  char msg[max_msg_size];
   1.238 +  vsnprintf(msg, max_msg_size, format, ap);
   1.239 +  msg[max_msg_size-1] = '\0';
   1.240 +  va_end(ap);
   1.241 +  _throw_msg(thread, file, line, h_name, msg);
   1.242 +}
   1.243 +
   1.244 +
   1.245 +// Creates an exception oop, calls the <init> method with the given signature.
   1.246 +// and returns a Handle
   1.247 +Handle Exceptions::new_exception(Thread *thread, Symbol* name,
   1.248 +                                 Symbol* signature, JavaCallArguments *args,
   1.249 +                                 Handle h_loader, Handle h_protection_domain) {
   1.250 +  assert(Universe::is_fully_initialized(),
   1.251 +    "cannot be called during initialization");
   1.252 +  assert(thread->is_Java_thread(), "can only be called by a Java thread");
   1.253 +  assert(!thread->has_pending_exception(), "already has exception");
   1.254 +
   1.255 +  Handle h_exception;
   1.256 +
   1.257 +  // Resolve exception klass
   1.258 +  Klass* ik = SystemDictionary::resolve_or_fail(name, h_loader, h_protection_domain, true, thread);
   1.259 +  instanceKlassHandle klass(thread, ik);
   1.260 +
   1.261 +  if (!thread->has_pending_exception()) {
   1.262 +    assert(klass.not_null(), "klass must exist");
   1.263 +    // We are about to create an instance - so make sure that klass is initialized
   1.264 +    klass->initialize(thread);
   1.265 +    if (!thread->has_pending_exception()) {
   1.266 +      // Allocate new exception
   1.267 +      h_exception = klass->allocate_instance_handle(thread);
   1.268 +      if (!thread->has_pending_exception()) {
   1.269 +        JavaValue result(T_VOID);
   1.270 +        args->set_receiver(h_exception);
   1.271 +        // Call constructor
   1.272 +        JavaCalls::call_special(&result, klass,
   1.273 +                                         vmSymbols::object_initializer_name(),
   1.274 +                                         signature,
   1.275 +                                         args,
   1.276 +                                         thread);
   1.277 +      }
   1.278 +    }
   1.279 +  }
   1.280 +
   1.281 +  // Check if another exception was thrown in the process, if so rethrow that one
   1.282 +  if (thread->has_pending_exception()) {
   1.283 +    h_exception = Handle(thread, thread->pending_exception());
   1.284 +    thread->clear_pending_exception();
   1.285 +  }
   1.286 +  return h_exception;
   1.287 +}
   1.288 +
   1.289 +// Creates an exception oop, calls the <init> method with the given signature.
   1.290 +// and returns a Handle
   1.291 +// Initializes the cause if cause non-null
   1.292 +Handle Exceptions::new_exception(Thread *thread, Symbol* name,
   1.293 +                                 Symbol* signature, JavaCallArguments *args,
   1.294 +                                 Handle h_cause,
   1.295 +                                 Handle h_loader, Handle h_protection_domain) {
   1.296 +  Handle h_exception = new_exception(thread, name, signature, args, h_loader, h_protection_domain);
   1.297 +
   1.298 +  // Future: object initializer should take a cause argument
   1.299 +  if (h_cause.not_null()) {
   1.300 +    assert(h_cause->is_a(SystemDictionary::Throwable_klass()),
   1.301 +        "exception cause is not a subclass of java/lang/Throwable");
   1.302 +    JavaValue result1(T_OBJECT);
   1.303 +    JavaCallArguments args1;
   1.304 +    args1.set_receiver(h_exception);
   1.305 +    args1.push_oop(h_cause);
   1.306 +    JavaCalls::call_virtual(&result1, h_exception->klass(),
   1.307 +                                      vmSymbols::initCause_name(),
   1.308 +                                      vmSymbols::throwable_throwable_signature(),
   1.309 +                                      &args1,
   1.310 +                                      thread);
   1.311 +  }
   1.312 +
   1.313 +  // Check if another exception was thrown in the process, if so rethrow that one
   1.314 +  if (thread->has_pending_exception()) {
   1.315 +    h_exception = Handle(thread, thread->pending_exception());
   1.316 +    thread->clear_pending_exception();
   1.317 +  }
   1.318 +  return h_exception;
   1.319 +}
   1.320 +
   1.321 +// Convenience method. Calls either the <init>() or <init>(Throwable) method when
   1.322 +// creating a new exception
   1.323 +Handle Exceptions::new_exception(Thread* thread, Symbol* name,
   1.324 +                                 Handle h_cause,
   1.325 +                                 Handle h_loader, Handle h_protection_domain,
   1.326 +                                 ExceptionMsgToUtf8Mode to_utf8_safe) {
   1.327 +  JavaCallArguments args;
   1.328 +  Symbol* signature = NULL;
   1.329 +  if (h_cause.is_null()) {
   1.330 +    signature = vmSymbols::void_method_signature();
   1.331 +  } else {
   1.332 +    signature = vmSymbols::throwable_void_signature();
   1.333 +    args.push_oop(h_cause);
   1.334 +  }
   1.335 +  return new_exception(thread, name, signature, &args, h_loader, h_protection_domain);
   1.336 +}
   1.337 +
   1.338 +// Convenience method. Calls either the <init>() or <init>(String) method when
   1.339 +// creating a new exception
   1.340 +Handle Exceptions::new_exception(Thread* thread, Symbol* name,
   1.341 +                                 const char* message, Handle h_cause,
   1.342 +                                 Handle h_loader, Handle h_protection_domain,
   1.343 +                                 ExceptionMsgToUtf8Mode to_utf8_safe) {
   1.344 +  JavaCallArguments args;
   1.345 +  Symbol* signature = NULL;
   1.346 +  if (message == NULL) {
   1.347 +    signature = vmSymbols::void_method_signature();
   1.348 +  } else {
   1.349 +    // We want to allocate storage, but we can't do that if there's
   1.350 +    // a pending exception, so we preserve any pending exception
   1.351 +    // around the allocation.
   1.352 +    // If we get an exception from the allocation, prefer that to
   1.353 +    // the exception we are trying to build, or the pending exception.
   1.354 +    // This is sort of like what PRESERVE_EXCEPTION_MARK does, except
   1.355 +    // for the preferencing and the early returns.
   1.356 +    Handle incoming_exception(thread, NULL);
   1.357 +    if (thread->has_pending_exception()) {
   1.358 +      incoming_exception = Handle(thread, thread->pending_exception());
   1.359 +      thread->clear_pending_exception();
   1.360 +    }
   1.361 +    Handle msg;
   1.362 +    if (to_utf8_safe == safe_to_utf8) {
   1.363 +      // Make a java UTF8 string.
   1.364 +      msg = java_lang_String::create_from_str(message, thread);
   1.365 +    } else {
   1.366 +      // Make a java string keeping the encoding scheme of the original string.
   1.367 +      msg = java_lang_String::create_from_platform_dependent_str(message, thread);
   1.368 +    }
   1.369 +    if (thread->has_pending_exception()) {
   1.370 +      Handle exception(thread, thread->pending_exception());
   1.371 +      thread->clear_pending_exception();
   1.372 +      return exception;
   1.373 +    }
   1.374 +    if (incoming_exception.not_null()) {
   1.375 +      return incoming_exception;
   1.376 +    }
   1.377 +    args.push_oop(msg);
   1.378 +    signature = vmSymbols::string_void_signature();
   1.379 +  }
   1.380 +  return new_exception(thread, name, signature, &args, h_cause, h_loader, h_protection_domain);
   1.381 +}
   1.382 +
   1.383 +// Another convenience method that creates handles for null class loaders and
   1.384 +// protection domains and null causes.
   1.385 +// If the last parameter 'to_utf8_mode' is safe_to_utf8,
   1.386 +// it means we can safely ignore the encoding scheme of the message string and
   1.387 +// convert it directly to a java UTF8 string. Otherwise, we need to take the
   1.388 +// encoding scheme of the string into account. One thing we should do at some
   1.389 +// point is to push this flag down to class java_lang_String since other
   1.390 +// classes may need similar functionalities.
   1.391 +Handle Exceptions::new_exception(Thread* thread, Symbol* name,
   1.392 +                                 const char* message,
   1.393 +                                 ExceptionMsgToUtf8Mode to_utf8_safe) {
   1.394 +
   1.395 +  Handle       h_loader(thread, NULL);
   1.396 +  Handle       h_prot(thread, NULL);
   1.397 +  Handle       h_cause(thread, NULL);
   1.398 +  return Exceptions::new_exception(thread, name, message, h_cause, h_loader,
   1.399 +                                   h_prot, to_utf8_safe);
   1.400 +}
   1.401 +
   1.402 +// Implementation of ExceptionMark
   1.403 +
   1.404 +ExceptionMark::ExceptionMark(Thread*& thread) {
   1.405 +  thread     = Thread::current();
   1.406 +  _thread    = thread;
   1.407 +  if (_thread->has_pending_exception()) {
   1.408 +    oop exception = _thread->pending_exception();
   1.409 +    _thread->clear_pending_exception(); // Needed to avoid infinite recursion
   1.410 +    exception->print();
   1.411 +    fatal("ExceptionMark constructor expects no pending exceptions");
   1.412 +  }
   1.413 +}
   1.414 +
   1.415 +
   1.416 +ExceptionMark::~ExceptionMark() {
   1.417 +  if (_thread->has_pending_exception()) {
   1.418 +    Handle exception(_thread, _thread->pending_exception());
   1.419 +    _thread->clear_pending_exception(); // Needed to avoid infinite recursion
   1.420 +    if (is_init_completed()) {
   1.421 +      exception->print();
   1.422 +      fatal("ExceptionMark destructor expects no pending exceptions");
   1.423 +    } else {
   1.424 +      vm_exit_during_initialization(exception);
   1.425 +    }
   1.426 +  }
   1.427 +}
   1.428 +
   1.429 +// ----------------------------------------------------------------------------------------
   1.430 +
   1.431 +#ifndef PRODUCT
   1.432 +// caller frees value_string if necessary
   1.433 +void Exceptions::debug_check_abort(const char *value_string, const char* message) {
   1.434 +  if (AbortVMOnException != NULL && value_string != NULL &&
   1.435 +      strstr(value_string, AbortVMOnException)) {
   1.436 +    if (AbortVMOnExceptionMessage == NULL || message == NULL ||
   1.437 +        strcmp(message, AbortVMOnExceptionMessage) == 0) {
   1.438 +      fatal(err_msg("Saw %s, aborting", value_string));
   1.439 +    }
   1.440 +  }
   1.441 +}
   1.442 +
   1.443 +void Exceptions::debug_check_abort(Handle exception, const char* message) {
   1.444 +  if (AbortVMOnException != NULL) {
   1.445 +    ResourceMark rm;
   1.446 +    if (message == NULL && exception->is_a(SystemDictionary::Throwable_klass())) {
   1.447 +      oop msg = java_lang_Throwable::message(exception);
   1.448 +      if (msg != NULL) {
   1.449 +        message = java_lang_String::as_utf8_string(msg);
   1.450 +      }
   1.451 +    }
   1.452 +    debug_check_abort(InstanceKlass::cast(exception()->klass())->external_name(), message);
   1.453 +  }
   1.454 +}
   1.455 +#endif

mercurial