1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "throwable.h" 18 19 #include "art_method-inl.h" 20 #include "class-inl.h" 21 #include "dex_file-inl.h" 22 #include "gc/accounting/card_table-inl.h" 23 #include "object-inl.h" 24 #include "object_array.h" 25 #include "object_array-inl.h" 26 #include "object_utils.h" 27 #include "utils.h" 28 #include "well_known_classes.h" 29 30 namespace art { 31 namespace mirror { 32 33 Class* Throwable::java_lang_Throwable_ = NULL; 34 35 void Throwable::SetCause(Throwable* cause) { 36 CHECK(cause != NULL); 37 CHECK(cause != this); 38 Throwable* current_cause = GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), 39 false); 40 CHECK(current_cause == NULL || current_cause == this); 41 SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), cause, false); 42 } 43 44 bool Throwable::IsCheckedException() const { 45 if (InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_Error))) { 46 return false; 47 } 48 return !InstanceOf(WellKnownClasses::ToClass(WellKnownClasses::java_lang_RuntimeException)); 49 } 50 51 std::string Throwable::Dump() const { 52 std::string result(PrettyTypeOf(this)); 53 result += ": "; 54 String* msg = GetDetailMessage(); 55 if (msg != NULL) { 56 result += msg->ToModifiedUtf8(); 57 } 58 result += "\n"; 59 Object* stack_state = GetStackState(); 60 // check stack state isn't missing or corrupt 61 if (stack_state != NULL && stack_state->IsObjectArray()) { 62 // Decode the internal stack trace into the depth and method trace 63 ObjectArray<Object>* method_trace = down_cast<ObjectArray<Object>*>(stack_state); 64 int32_t depth = method_trace->GetLength() - 1; 65 IntArray* pc_trace = down_cast<IntArray*>(method_trace->Get(depth)); 66 MethodHelper mh; 67 for (int32_t i = 0; i < depth; ++i) { 68 ArtMethod* method = down_cast<ArtMethod*>(method_trace->Get(i)); 69 mh.ChangeMethod(method); 70 uint32_t dex_pc = pc_trace->Get(i); 71 int32_t line_number = mh.GetLineNumFromDexPC(dex_pc); 72 const char* source_file = mh.GetDeclaringClassSourceFile(); 73 result += StringPrintf(" at %s (%s:%d)\n", PrettyMethod(method, true).c_str(), 74 source_file, line_number); 75 } 76 } 77 Throwable* cause = GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false); 78 if (cause != NULL && cause != this) { // Constructor makes cause == this by default. 79 result += "Caused by: "; 80 result += cause->Dump(); 81 } 82 return result; 83 } 84 85 void Throwable::SetClass(Class* java_lang_Throwable) { 86 CHECK(java_lang_Throwable_ == NULL); 87 CHECK(java_lang_Throwable != NULL); 88 java_lang_Throwable_ = java_lang_Throwable; 89 } 90 91 void Throwable::ResetClass() { 92 CHECK(java_lang_Throwable_ != NULL); 93 java_lang_Throwable_ = NULL; 94 } 95 96 } // namespace mirror 97 } // namespace art 98