1 /*
   2  * Copyright (c) 1998, 2007, 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 "incls/_precompiled.incl"
  26 #include "incls/_exceptions.cpp.incl"
  27 
  28 
  29 // Implementation of ThreadShadow
  30 void check_ThreadShadow() {
  31   const ByteSize offset1 = byte_offset_of(ThreadShadow, _pending_exception);
  32   const ByteSize offset2 = Thread::pending_exception_offset();
  33   if (offset1 != offset2) fatal("ThreadShadow::_pending_exception is not positioned correctly");
  34 }
  35 
  36 
  37 void ThreadShadow::set_pending_exception(oop exception, const char* file, int line) {
  38   assert(exception != NULL && exception->is_oop(), "invalid exception oop");
  39   _pending_exception = exception;
  40   _exception_file    = file;
  41   _exception_line    = line;
  42 }
  43 
  44 void ThreadShadow::clear_pending_exception() {
  45   if (TraceClearedExceptions) {
  46     if (_pending_exception != NULL) {
  47       tty->print_cr("Thread::clear_pending_exception: cleared exception:");
  48       _pending_exception->print();
  49     }
  50   }
  51   _pending_exception = NULL;
  52   _exception_file    = NULL;
  53   _exception_line    = 0;
  54 }
  55 // Implementation of Exceptions
  56 
  57 bool Exceptions::special_exception(Thread* thread, const char* file, int line, Handle h_exception) {
  58   // bootstrapping check
  59   if (!Universe::is_fully_initialized()) {
  60    vm_exit_during_initialization(h_exception);
  61    ShouldNotReachHere();
  62   }
  63 
  64 #ifdef ASSERT
  65   // Check for trying to throw stack overflow before initialization is complete
  66   // to prevent infinite recursion trying to initialize stack overflow without
  67   // adequate stack space.
  68   // This can happen with stress testing a large value of StackShadowPages
  69   if (h_exception()->klass() == SystemDictionary::StackOverflowError_klass()) {
  70     instanceKlass* ik = instanceKlass::cast(h_exception->klass());
  71     assert(ik->is_initialized(),
  72            "need to increase min_stack_allowed calculation");
  73   }
  74 #endif // ASSERT
  75 
  76   if (thread->is_VM_thread()
  77       || thread->is_Compiler_thread() ) {
  78     // We do not care what kind of exception we get for the vm-thread or a thread which
  79     // is compiling.  We just install a dummy exception object
  80     thread->set_pending_exception(Universe::vm_exception(), file, line);
  81     return true;
  82   }
  83 
  84   return false;
  85 }
  86 
  87 bool Exceptions::special_exception(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message) {
  88   // bootstrapping check
  89   if (!Universe::is_fully_initialized()) {
  90     if (h_name.is_null()) {
  91       // atleast an informative message.
  92       vm_exit_during_initialization("Exception", message);
  93     } else {
  94       vm_exit_during_initialization(h_name, message);
  95     }
  96     ShouldNotReachHere();
  97   }
  98 
  99   if (thread->is_VM_thread()
 100       || thread->is_Compiler_thread() ) {
 101     // We do not care what kind of exception we get for the vm-thread or a thread which
 102     // is compiling.  We just install a dummy exception object
 103     thread->set_pending_exception(Universe::vm_exception(), file, line);
 104     return true;
 105   }
 106   return false;
 107 }
 108 
 109 // This method should only be called from generated code,
 110 // therefore the exception oop should be in the oopmap.
 111 void Exceptions::_throw_oop(Thread* thread, const char* file, int line, oop exception) {
 112   assert(exception != NULL, "exception should not be NULL");
 113   Handle h_exception = Handle(thread, exception);
 114   _throw(thread, file, line, h_exception);
 115 }
 116 
 117 void Exceptions::_throw(Thread* thread, const char* file, int line, Handle h_exception, const char* message) {
 118   assert(h_exception() != NULL, "exception should not be NULL");
 119 
 120   // tracing (do this up front - so it works during boot strapping)
 121   if (TraceExceptions) {
 122     ttyLocker ttyl;
 123     ResourceMark rm;
 124     tty->print_cr("Exception <%s>%s%s (" INTPTR_FORMAT " ) \n"
 125                   "thrown [%s, line %d]\nfor thread " INTPTR_FORMAT,
 126                   h_exception->print_value_string(),
 127                   message ? ": " : "", message ? message : "",
 128                   (address)h_exception(), file, line, thread);
 129   }
 130   // for AbortVMOnException flag
 131   NOT_PRODUCT(Exceptions::debug_check_abort(h_exception, message));
 132 
 133   // Check for special boot-strapping/vm-thread handling
 134   if (special_exception(thread, file, line, h_exception)) return;
 135 
 136   assert(h_exception->is_a(SystemDictionary::Throwable_klass()), "exception is not a subclass of java/lang/Throwable");
 137 
 138   // set the pending exception
 139   thread->set_pending_exception(h_exception(), file, line);
 140 
 141   // vm log
 142   Events::log("throw_exception " INTPTR_FORMAT, (address)h_exception());
 143 }
 144 
 145 
 146 void Exceptions::_throw_msg(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message, Handle h_loader, Handle h_protection_domain) {
 147   // Check for special boot-strapping/vm-thread handling
 148   if (special_exception(thread, file, line, h_name, message)) return;
 149   // Create and throw exception
 150   Handle h_cause(thread, NULL);
 151   Handle h_exception = new_exception(thread, h_name, message, h_cause, h_loader, h_protection_domain);
 152   _throw(thread, file, line, h_exception, message);
 153 }
 154 
 155 // Throw an exception with a message and a cause
 156 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) {
 157   // Check for special boot-strapping/vm-thread handling
 158   if (special_exception(thread, file, line, h_name, message)) return;
 159   // Create and throw exception and init cause
 160   Handle h_exception = new_exception(thread, h_name, message, h_cause, h_loader, h_protection_domain);
 161   _throw(thread, file, line, h_exception, message);
 162 }
 163 
 164 // This version creates handles and calls the other version
 165 void Exceptions::_throw_msg(Thread* thread, const char* file, int line,
 166                             symbolOop name, const char* message) {
 167   symbolHandle h_name(thread, name);
 168   Handle       h_loader(thread, NULL);
 169   Handle       h_protection_domain(thread, NULL);
 170   Exceptions::_throw_msg(thread, file, line, h_name, message, h_loader, h_protection_domain);
 171 }
 172 
 173 // This version already has a handle for name
 174 void Exceptions::_throw_msg(Thread* thread, const char* file, int line,
 175                             symbolHandle name, const char* message) {
 176   Handle       h_loader(thread, NULL);
 177   Handle       h_protection_domain(thread, NULL);
 178   Exceptions::_throw_msg(thread, file, line, name, message, h_loader, h_protection_domain);
 179 }
 180 
 181 // This version already has a handle for name
 182 void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line,
 183                             symbolHandle name, const char* message, Handle cause) {
 184   Handle       h_loader(thread, NULL);
 185   Handle       h_protection_domain(thread, NULL);
 186   Exceptions::_throw_msg_cause(thread, file, line, name, message, cause, h_loader, h_protection_domain);
 187 }
 188 
 189 void Exceptions::_throw_args(Thread* thread, const char* file, int line, symbolHandle h_name, symbolHandle h_signature, JavaCallArguments *args) {
 190   // Check for special boot-strapping/vm-thread handling
 191   if (special_exception(thread, file, line, h_name, NULL)) return;
 192   // Create and throw exception
 193   Handle h_loader(thread, NULL);
 194   Handle h_prot(thread, NULL);
 195   Handle h_cause(thread, NULL);
 196   Handle exception = new_exception(thread, h_name, h_signature, args, h_cause, h_loader, h_prot);
 197   _throw(thread, file, line, exception);
 198 }
 199 
 200 
 201 void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line) {
 202   Handle exception;
 203   if (!THREAD->has_pending_exception()) {
 204     klassOop k = SystemDictionary::StackOverflowError_klass();
 205     oop e = instanceKlass::cast(k)->allocate_instance(CHECK);
 206     exception = Handle(THREAD, e);  // fill_in_stack trace does gc
 207     assert(instanceKlass::cast(k)->is_initialized(), "need to increase min_stack_allowed calculation");
 208     if (StackTraceInThrowable) {
 209       java_lang_Throwable::fill_in_stack_trace(exception);
 210     }
 211   } else {
 212     // if prior exception, throw that one instead
 213     exception = Handle(THREAD, THREAD->pending_exception());
 214   }
 215   _throw_oop(THREAD, file, line, exception());
 216 }
 217 
 218 void Exceptions::fthrow(Thread* thread, const char* file, int line, symbolHandle h_name, const char* format, ...) {
 219   const int max_msg_size = 1024;
 220   va_list ap;
 221   va_start(ap, format);
 222   char msg[max_msg_size];
 223   vsnprintf(msg, max_msg_size, format, ap);
 224   msg[max_msg_size-1] = '\0';
 225   va_end(ap);
 226   _throw_msg(thread, file, line, h_name, msg);
 227 }
 228 
 229 // Creates an exception oop, calls the <init> method with the given signature.
 230 // and returns a Handle
 231 // Initializes the cause if cause non-null
 232 Handle Exceptions::new_exception(Thread *thread, symbolHandle h_name,
 233                                  symbolHandle signature,
 234                                  JavaCallArguments *args,
 235                                  Handle h_cause, Handle h_loader,
 236                                  Handle h_protection_domain) {
 237   assert(Universe::is_fully_initialized(),
 238     "cannot be called during initialization");
 239   assert(thread->is_Java_thread(), "can only be called by a Java thread");
 240   assert(!thread->has_pending_exception(), "already has exception");
 241 
 242   Handle h_exception;
 243 
 244   // Resolve exception klass
 245   klassOop ik = SystemDictionary::resolve_or_fail(h_name, h_loader, h_protection_domain, true, thread);
 246   instanceKlassHandle klass (thread, ik);
 247 
 248   if (!thread->has_pending_exception()) {
 249     assert(klass.not_null(), "klass must exist");
 250     // We are about to create an instance - so make sure that klass is initialized
 251     klass->initialize(thread);
 252     if (!thread->has_pending_exception()) {
 253       // Allocate new exception
 254       h_exception = klass->allocate_instance_handle(thread);
 255       if (!thread->has_pending_exception()) {
 256         JavaValue result(T_VOID);
 257         args->set_receiver(h_exception);
 258         // Call constructor
 259         JavaCalls::call_special(&result, klass,
 260                                          vmSymbolHandles::object_initializer_name(),
 261                                          signature,
 262                                          args,
 263                                          thread);
 264 
 265       }
 266     }
 267 
 268     // Future: object initializer should take a cause argument
 269     if (h_cause() != NULL) {
 270       assert(h_cause->is_a(SystemDictionary::Throwable_klass()),
 271           "exception cause is not a subclass of java/lang/Throwable");
 272       JavaValue result1(T_OBJECT);
 273       JavaCallArguments args1;
 274       args1.set_receiver(h_exception);
 275       args1.push_oop(h_cause);
 276       JavaCalls::call_virtual(&result1, klass,
 277                                      vmSymbolHandles::initCause_name(),
 278                                      vmSymbolHandles::throwable_throwable_signature(),
 279                                      &args1,
 280                                      thread);
 281     }
 282   }
 283 
 284   // Check if another exception was thrown in the process, if so rethrow that one
 285   if (thread->has_pending_exception()) {
 286     h_exception = Handle(thread, thread->pending_exception());
 287     thread->clear_pending_exception();
 288   }
 289   return h_exception;
 290 }
 291 
 292 // Convenience method. Calls either the <init>() or <init>(String) method when
 293 // creating a new exception
 294 Handle Exceptions::new_exception(Thread* thread, symbolHandle h_name,
 295                                  const char* message, Handle h_cause,
 296                                  Handle h_loader,
 297                                  Handle h_protection_domain,
 298                                  ExceptionMsgToUtf8Mode to_utf8_safe) {
 299   JavaCallArguments args;
 300   symbolHandle signature;
 301   if (message == NULL) {
 302     signature = vmSymbolHandles::void_method_signature();
 303   } else {
 304     // We want to allocate storage, but we can't do that if there's
 305     // a pending exception, so we preserve any pending exception
 306     // around the allocation.
 307     // If we get an exception from the allocation, prefer that to
 308     // the exception we are trying to build, or the pending exception.
 309     // This is sort of like what PRESERVE_EXCEPTION_MARK does, except
 310     // for the preferencing and the early returns.
 311     Handle incoming_exception (thread, NULL);
 312     if (thread->has_pending_exception()) {
 313       incoming_exception = Handle(thread, thread->pending_exception());
 314       thread->clear_pending_exception();
 315     }
 316     Handle msg;
 317     if (to_utf8_safe == safe_to_utf8) {
 318       // Make a java UTF8 string.
 319       msg = java_lang_String::create_from_str(message, thread);
 320     } else {
 321       // Make a java string keeping the encoding scheme of the original string.
 322       msg = java_lang_String::create_from_platform_dependent_str(message, thread);
 323     }
 324     if (thread->has_pending_exception()) {
 325       Handle exception(thread, thread->pending_exception());
 326       thread->clear_pending_exception();
 327       return exception;
 328     }
 329     if (incoming_exception.not_null()) {
 330       return incoming_exception;
 331     }
 332     args.push_oop(msg);
 333     signature = vmSymbolHandles::string_void_signature();
 334   }
 335   return new_exception(thread, h_name, signature, &args, h_cause, h_loader, h_protection_domain);
 336 }
 337 
 338 // Another convenience method that creates handles for null class loaders and
 339 // protection domains and null causes.
 340 // If the last parameter 'to_utf8_mode' is safe_to_utf8,
 341 // it means we can safely ignore the encoding scheme of the message string and
 342 // convert it directly to a java UTF8 string. Otherwise, we need to take the
 343 // encoding scheme of the string into account. One thing we should do at some
 344 // point is to push this flag down to class java_lang_String since other
 345 // classes may need similar functionalities.
 346 Handle Exceptions::new_exception(Thread* thread,
 347                                  symbolOop name,
 348                                  const char* message,
 349                                  ExceptionMsgToUtf8Mode to_utf8_safe) {
 350 
 351   symbolHandle h_name(thread, name);
 352   Handle       h_loader(thread, NULL);
 353   Handle       h_prot(thread, NULL);
 354   Handle       h_cause(thread, NULL);
 355   return Exceptions::new_exception(thread, h_name, message, h_cause, h_loader,
 356                                    h_prot, to_utf8_safe);
 357 }
 358 
 359 // Implementation of ExceptionMark
 360 
 361 ExceptionMark::ExceptionMark(Thread*& thread) {
 362   thread     = Thread::current();
 363   _thread    = thread;
 364   if (_thread->has_pending_exception()) {
 365     oop exception = _thread->pending_exception();
 366     _thread->clear_pending_exception(); // Needed to avoid infinite recursion
 367     exception->print();
 368     fatal("ExceptionMark constructor expects no pending exceptions");
 369   }
 370 }
 371 
 372 
 373 ExceptionMark::~ExceptionMark() {
 374   if (_thread->has_pending_exception()) {
 375     Handle exception(_thread, _thread->pending_exception());
 376     _thread->clear_pending_exception(); // Needed to avoid infinite recursion
 377     if (is_init_completed()) {
 378       exception->print();
 379       fatal("ExceptionMark destructor expects no pending exceptions");
 380     } else {
 381       vm_exit_during_initialization(exception);
 382     }
 383   }
 384 }
 385 
 386 // ----------------------------------------------------------------------------------------
 387 
 388 #ifndef PRODUCT
 389 // caller frees value_string if necessary
 390 void Exceptions::debug_check_abort(const char *value_string, const char* message) {
 391   if (AbortVMOnException != NULL && value_string != NULL &&
 392       strstr(value_string, AbortVMOnException)) {
 393     if (AbortVMOnExceptionMessage == NULL || message == NULL ||
 394         strcmp(message, AbortVMOnExceptionMessage) == 0) {
 395       fatal(err_msg("Saw %s, aborting", value_string));
 396     }
 397   }
 398 }
 399 
 400 void Exceptions::debug_check_abort(Handle exception, const char* message) {
 401   if (AbortVMOnException != NULL) {
 402     ResourceMark rm;
 403     if (message == NULL && exception->is_a(SystemDictionary::Throwable_klass())) {
 404       oop msg = java_lang_Throwable::message(exception);
 405       if (msg != NULL) {
 406         message = java_lang_String::as_utf8_string(msg);
 407       }
 408     }
 409     debug_check_abort(instanceKlass::cast(exception()->klass())->external_name(), message);
 410   }
 411 }
 412 #endif