src/share/vm/utilities/exceptions.cpp

changeset 435
a61af66fc99e
child 1446
fcb148c6b605
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/utilities/exceptions.cpp	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,388 @@
     1.4 +/*
     1.5 + * Copyright 1998-2007 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.24 + * have any questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "incls/_precompiled.incl"
    1.29 +#include "incls/_exceptions.cpp.incl"
    1.30 +
    1.31 +
    1.32 +// Implementation of ThreadShadow
    1.33 +void check_ThreadShadow() {
    1.34 +  const ByteSize offset1 = byte_offset_of(ThreadShadow, _pending_exception);
    1.35 +  const ByteSize offset2 = Thread::pending_exception_offset();
    1.36 +  if (offset1 != offset2) fatal("ThreadShadow::_pending_exception is not positioned correctly");
    1.37 +}
    1.38 +
    1.39 +
    1.40 +void ThreadShadow::set_pending_exception(oop exception, const char* file, int line) {
    1.41 +  assert(exception != NULL && exception->is_oop(), "invalid exception oop");
    1.42 +  _pending_exception = exception;
    1.43 +  _exception_file    = file;
    1.44 +  _exception_line    = line;
    1.45 +}
    1.46 +
    1.47 +void ThreadShadow::clear_pending_exception() {
    1.48 +  if (TraceClearedExceptions) {
    1.49 +    if (_pending_exception != NULL) {
    1.50 +      tty->print_cr("Thread::clear_pending_exception: cleared exception:");
    1.51 +      _pending_exception->print();
    1.52 +    }
    1.53 +  }
    1.54 +  _pending_exception = NULL;
    1.55 +  _exception_file    = NULL;
    1.56 +  _exception_line    = 0;
    1.57 +}
    1.58 +// Implementation of Exceptions
    1.59 +
    1.60 +bool Exceptions::special_exception(Thread* thread, const char* file, int line, Handle h_exception) {
    1.61 +  // bootstrapping check
    1.62 +  if (!Universe::is_fully_initialized()) {
    1.63 +   vm_exit_during_initialization(h_exception);
    1.64 +   ShouldNotReachHere();
    1.65 +  }
    1.66 +
    1.67 +  if (thread->is_VM_thread()
    1.68 +      || thread->is_Compiler_thread() ) {
    1.69 +    // We do not care what kind of exception we get for the vm-thread or a thread which
    1.70 +    // is compiling.  We just install a dummy exception object
    1.71 +    thread->set_pending_exception(Universe::vm_exception(), file, line);
    1.72 +    return true;
    1.73 +  }
    1.74 +
    1.75 +  return false;
    1.76 +}
    1.77 +
    1.78 +bool Exceptions::special_exception(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message) {
    1.79 +  // bootstrapping check
    1.80 +  if (!Universe::is_fully_initialized()) {
    1.81 +    if (h_name.is_null()) {
    1.82 +      // atleast an informative message.
    1.83 +      vm_exit_during_initialization("Exception", message);
    1.84 +    } else {
    1.85 +      vm_exit_during_initialization(h_name, message);
    1.86 +    }
    1.87 +    ShouldNotReachHere();
    1.88 +  }
    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 +// This method should only be called from generated code,
   1.102 +// therefore the exception oop should be in the oopmap.
   1.103 +void Exceptions::_throw_oop(Thread* thread, const char* file, int line, oop exception) {
   1.104 +  assert(exception != NULL, "exception should not be NULL");
   1.105 +  Handle h_exception = Handle(thread, exception);
   1.106 +  _throw(thread, file, line, h_exception);
   1.107 +}
   1.108 +
   1.109 +void Exceptions::_throw(Thread* thread, const char* file, int line, Handle h_exception) {
   1.110 +  assert(h_exception() != NULL, "exception should not be NULL");
   1.111 +
   1.112 +  // tracing (do this up front - so it works during boot strapping)
   1.113 +  if (TraceExceptions) {
   1.114 +    ttyLocker ttyl;
   1.115 +    ResourceMark rm;
   1.116 +    tty->print_cr("Exception <%s> (" INTPTR_FORMAT " ) \nthrown [%s, line %d]\nfor thread " INTPTR_FORMAT,
   1.117 +                      h_exception->print_value_string(), (address)h_exception(), file, line, thread);
   1.118 +  }
   1.119 +  // for AbortVMOnException flag
   1.120 +  NOT_PRODUCT(Exceptions::debug_check_abort(h_exception));
   1.121 +
   1.122 +  // Check for special boot-strapping/vm-thread handling
   1.123 +  if (special_exception(thread, file, line, h_exception)) return;
   1.124 +
   1.125 +  assert(h_exception->is_a(SystemDictionary::throwable_klass()), "exception is not a subclass of java/lang/Throwable");
   1.126 +
   1.127 +  // set the pending exception
   1.128 +  thread->set_pending_exception(h_exception(), file, line);
   1.129 +
   1.130 +  // vm log
   1.131 +  Events::log("throw_exception " INTPTR_FORMAT, (address)h_exception());
   1.132 +}
   1.133 +
   1.134 +
   1.135 +void Exceptions::_throw_msg(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message, Handle h_loader, Handle h_protection_domain) {
   1.136 +  // Check for special boot-strapping/vm-thread handling
   1.137 +  if (special_exception(thread, file, line, h_name, message)) return;
   1.138 +  // Create and throw exception
   1.139 +  Handle h_cause(thread, NULL);
   1.140 +  Handle h_exception = new_exception(thread, h_name, message, h_cause, h_loader, h_protection_domain);
   1.141 +  _throw(thread, file, line, h_exception);
   1.142 +}
   1.143 +
   1.144 +// Throw an exception with a message and a cause
   1.145 +void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message, Handle h_cause, Handle h_loader, Handle h_protection_domain) {
   1.146 +  // Check for special boot-strapping/vm-thread handling
   1.147 +  if (special_exception(thread, file, line, h_name, message)) return;
   1.148 +  // Create and throw exception and init cause
   1.149 +  Handle h_exception = new_exception(thread, h_name, message, h_cause, h_loader, h_protection_domain);
   1.150 +  _throw(thread, file, line, h_exception);
   1.151 +}
   1.152 +
   1.153 +// This version creates handles and calls the other version
   1.154 +void Exceptions::_throw_msg(Thread* thread, const char* file, int line,
   1.155 +                            symbolOop name, const char* message) {
   1.156 +  symbolHandle h_name(thread, name);
   1.157 +  Handle       h_loader(thread, NULL);
   1.158 +  Handle       h_protection_domain(thread, NULL);
   1.159 +  Exceptions::_throw_msg(thread, file, line, h_name, message, h_loader, h_protection_domain);
   1.160 +}
   1.161 +
   1.162 +// This version already has a handle for name
   1.163 +void Exceptions::_throw_msg(Thread* thread, const char* file, int line,
   1.164 +                            symbolHandle name, const char* message) {
   1.165 +  Handle       h_loader(thread, NULL);
   1.166 +  Handle       h_protection_domain(thread, NULL);
   1.167 +  Exceptions::_throw_msg(thread, file, line, name, message, h_loader, h_protection_domain);
   1.168 +}
   1.169 +
   1.170 +// This version already has a handle for name
   1.171 +void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line,
   1.172 +                            symbolHandle name, const char* message, Handle cause) {
   1.173 +  Handle       h_loader(thread, NULL);
   1.174 +  Handle       h_protection_domain(thread, NULL);
   1.175 +  Exceptions::_throw_msg_cause(thread, file, line, name, message, cause, h_loader, h_protection_domain);
   1.176 +}
   1.177 +
   1.178 +void Exceptions::_throw_args(Thread* thread, const char* file, int line, symbolHandle h_name, symbolHandle h_signature, JavaCallArguments *args) {
   1.179 +  // Check for special boot-strapping/vm-thread handling
   1.180 +  if (special_exception(thread, file, line, h_name, NULL)) return;
   1.181 +  // Create and throw exception
   1.182 +  Handle h_loader(thread, NULL);
   1.183 +  Handle h_prot(thread, NULL);
   1.184 +  Handle h_cause(thread, NULL);
   1.185 +  Handle exception = new_exception(thread, h_name, h_signature, args, h_cause, h_loader, h_prot);
   1.186 +  _throw(thread, file, line, exception);
   1.187 +}
   1.188 +
   1.189 +
   1.190 +void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line) {
   1.191 +  Handle exception;
   1.192 +  if (!THREAD->has_pending_exception()) {
   1.193 +    klassOop k = SystemDictionary::StackOverflowError_klass();
   1.194 +    oop e = instanceKlass::cast(k)->allocate_instance(CHECK);
   1.195 +    exception = Handle(THREAD, e);  // fill_in_stack trace does gc
   1.196 +    if (StackTraceInThrowable) {
   1.197 +      java_lang_Throwable::fill_in_stack_trace(exception);
   1.198 +    }
   1.199 +  } else {
   1.200 +    // if prior exception, throw that one instead
   1.201 +    exception = Handle(THREAD, THREAD->pending_exception());
   1.202 +  }
   1.203 +  _throw_oop(THREAD, file, line, exception());
   1.204 +}
   1.205 +
   1.206 +void Exceptions::fthrow(Thread* thread, const char* file, int line, symbolHandle h_name, const char* format, ...) {
   1.207 +  const int max_msg_size = 1024;
   1.208 +  va_list ap;
   1.209 +  va_start(ap, format);
   1.210 +  char msg[max_msg_size];
   1.211 +  vsnprintf(msg, max_msg_size, format, ap);
   1.212 +  msg[max_msg_size-1] = '\0';
   1.213 +  va_end(ap);
   1.214 +  _throw_msg(thread, file, line, h_name, msg);
   1.215 +}
   1.216 +
   1.217 +// Creates an exception oop, calls the <init> method with the given signature.
   1.218 +// and returns a Handle
   1.219 +// Initializes the cause if cause non-null
   1.220 +Handle Exceptions::new_exception(Thread *thread, symbolHandle h_name,
   1.221 +                                 symbolHandle signature,
   1.222 +                                 JavaCallArguments *args,
   1.223 +                                 Handle h_cause, Handle h_loader,
   1.224 +                                 Handle h_protection_domain) {
   1.225 +  assert(Universe::is_fully_initialized(),
   1.226 +    "cannot be called during initialization");
   1.227 +  assert(thread->is_Java_thread(), "can only be called by a Java thread");
   1.228 +  assert(!thread->has_pending_exception(), "already has exception");
   1.229 +
   1.230 +  Handle h_exception;
   1.231 +
   1.232 +  // Resolve exception klass
   1.233 +  klassOop ik = SystemDictionary::resolve_or_fail(h_name, h_loader, h_protection_domain, true, thread);
   1.234 +  instanceKlassHandle klass (thread, ik);
   1.235 +
   1.236 +  if (!thread->has_pending_exception()) {
   1.237 +    assert(klass.not_null(), "klass must exist");
   1.238 +    // We are about to create an instance - so make sure that klass is initialized
   1.239 +    klass->initialize(thread);
   1.240 +    if (!thread->has_pending_exception()) {
   1.241 +      // Allocate new exception
   1.242 +      h_exception = klass->allocate_instance_handle(thread);
   1.243 +      if (!thread->has_pending_exception()) {
   1.244 +        JavaValue result(T_VOID);
   1.245 +        args->set_receiver(h_exception);
   1.246 +        // Call constructor
   1.247 +        JavaCalls::call_special(&result, klass,
   1.248 +                                         vmSymbolHandles::object_initializer_name(),
   1.249 +                                         signature,
   1.250 +                                         args,
   1.251 +                                         thread);
   1.252 +
   1.253 +      }
   1.254 +    }
   1.255 +
   1.256 +    // Future: object initializer should take a cause argument
   1.257 +    if (h_cause() != NULL) {
   1.258 +      assert(h_cause->is_a(SystemDictionary::throwable_klass()),
   1.259 +          "exception cause is not a subclass of java/lang/Throwable");
   1.260 +      JavaValue result1(T_OBJECT);
   1.261 +      JavaCallArguments args1;
   1.262 +      args1.set_receiver(h_exception);
   1.263 +      args1.push_oop(h_cause);
   1.264 +      JavaCalls::call_virtual(&result1, klass,
   1.265 +                                     vmSymbolHandles::initCause_name(),
   1.266 +                                     vmSymbolHandles::throwable_throwable_signature(),
   1.267 +                                     &args1,
   1.268 +                                     thread);
   1.269 +    }
   1.270 +  }
   1.271 +
   1.272 +  // Check if another exception was thrown in the process, if so rethrow that one
   1.273 +  if (thread->has_pending_exception()) {
   1.274 +    h_exception = Handle(thread, thread->pending_exception());
   1.275 +    thread->clear_pending_exception();
   1.276 +  }
   1.277 +  return h_exception;
   1.278 +}
   1.279 +
   1.280 +// Convenience method. Calls either the <init>() or <init>(String) method when
   1.281 +// creating a new exception
   1.282 +Handle Exceptions::new_exception(Thread* thread, symbolHandle h_name,
   1.283 +                                 const char* message, Handle h_cause,
   1.284 +                                 Handle h_loader,
   1.285 +                                 Handle h_protection_domain,
   1.286 +                                 ExceptionMsgToUtf8Mode to_utf8_safe) {
   1.287 +  JavaCallArguments args;
   1.288 +  symbolHandle signature;
   1.289 +  if (message == NULL) {
   1.290 +    signature = vmSymbolHandles::void_method_signature();
   1.291 +  } else {
   1.292 +    // We want to allocate storage, but we can't do that if there's
   1.293 +    // a pending exception, so we preserve any pending exception
   1.294 +    // around the allocation.
   1.295 +    // If we get an exception from the allocation, prefer that to
   1.296 +    // the exception we are trying to build, or the pending exception.
   1.297 +    // This is sort of like what PRESERVE_EXCEPTION_MARK does, except
   1.298 +    // for the preferencing and the early returns.
   1.299 +    Handle incoming_exception (thread, NULL);
   1.300 +    if (thread->has_pending_exception()) {
   1.301 +      incoming_exception = Handle(thread, thread->pending_exception());
   1.302 +      thread->clear_pending_exception();
   1.303 +    }
   1.304 +    Handle msg;
   1.305 +    if (to_utf8_safe == safe_to_utf8) {
   1.306 +      // Make a java UTF8 string.
   1.307 +      msg = java_lang_String::create_from_str(message, thread);
   1.308 +    } else {
   1.309 +      // Make a java string keeping the encoding scheme of the original string.
   1.310 +      msg = java_lang_String::create_from_platform_dependent_str(message, thread);
   1.311 +    }
   1.312 +    if (thread->has_pending_exception()) {
   1.313 +      Handle exception(thread, thread->pending_exception());
   1.314 +      thread->clear_pending_exception();
   1.315 +      return exception;
   1.316 +    }
   1.317 +    if (incoming_exception.not_null()) {
   1.318 +      return incoming_exception;
   1.319 +    }
   1.320 +    args.push_oop(msg);
   1.321 +    signature = vmSymbolHandles::string_void_signature();
   1.322 +  }
   1.323 +  return new_exception(thread, h_name, signature, &args, h_cause, h_loader, h_protection_domain);
   1.324 +}
   1.325 +
   1.326 +// Another convenience method that creates handles for null class loaders and
   1.327 +// protection domains and null causes.
   1.328 +// If the last parameter 'to_utf8_mode' is safe_to_utf8,
   1.329 +// it means we can safely ignore the encoding scheme of the message string and
   1.330 +// convert it directly to a java UTF8 string. Otherwise, we need to take the
   1.331 +// encoding scheme of the string into account. One thing we should do at some
   1.332 +// point is to push this flag down to class java_lang_String since other
   1.333 +// classes may need similar functionalities.
   1.334 +Handle Exceptions::new_exception(Thread* thread,
   1.335 +                                 symbolOop name,
   1.336 +                                 const char* message,
   1.337 +                                 ExceptionMsgToUtf8Mode to_utf8_safe) {
   1.338 +
   1.339 +  symbolHandle h_name(thread, name);
   1.340 +  Handle       h_loader(thread, NULL);
   1.341 +  Handle       h_prot(thread, NULL);
   1.342 +  Handle       h_cause(thread, NULL);
   1.343 +  return Exceptions::new_exception(thread, h_name, message, h_cause, h_loader,
   1.344 +                                   h_prot, to_utf8_safe);
   1.345 +}
   1.346 +
   1.347 +// Implementation of ExceptionMark
   1.348 +
   1.349 +ExceptionMark::ExceptionMark(Thread*& thread) {
   1.350 +  thread     = Thread::current();
   1.351 +  _thread    = thread;
   1.352 +  if (_thread->has_pending_exception()) {
   1.353 +    oop exception = _thread->pending_exception();
   1.354 +    _thread->clear_pending_exception(); // Needed to avoid infinite recursion
   1.355 +    exception->print();
   1.356 +    fatal("ExceptionMark constructor expects no pending exceptions");
   1.357 +  }
   1.358 +}
   1.359 +
   1.360 +
   1.361 +ExceptionMark::~ExceptionMark() {
   1.362 +  if (_thread->has_pending_exception()) {
   1.363 +    Handle exception(_thread, _thread->pending_exception());
   1.364 +    _thread->clear_pending_exception(); // Needed to avoid infinite recursion
   1.365 +    if (is_init_completed()) {
   1.366 +      exception->print();
   1.367 +      fatal("ExceptionMark destructor expects no pending exceptions");
   1.368 +    } else {
   1.369 +      vm_exit_during_initialization(exception);
   1.370 +    }
   1.371 +  }
   1.372 +}
   1.373 +
   1.374 +// ----------------------------------------------------------------------------------------
   1.375 +
   1.376 +#ifndef PRODUCT
   1.377 +// caller frees value_string if necessary
   1.378 +void Exceptions::debug_check_abort(const char *value_string) {
   1.379 +  if (AbortVMOnException != NULL && value_string != NULL &&
   1.380 +      strstr(value_string, AbortVMOnException)) {
   1.381 +    fatal1("Saw %s, aborting", value_string);
   1.382 +  }
   1.383 +}
   1.384 +
   1.385 +void Exceptions::debug_check_abort(Handle exception) {
   1.386 +  if (AbortVMOnException != NULL) {
   1.387 +    ResourceMark rm;
   1.388 +    debug_check_abort(instanceKlass::cast(exception()->klass())->external_name());
   1.389 +  }
   1.390 +}
   1.391 +#endif

mercurial