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