summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/thread.cc82
-rw-r--r--test/141-class-unload/expected.txt5
-rw-r--r--test/141-class-unload/src-ex/IntHolder.java4
-rw-r--r--test/141-class-unload/src/Main.java12
4 files changed, 22 insertions, 81 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 65f71efc06..82e6fb0f00 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1966,32 +1966,15 @@ class BuildInternalStackTraceVisitor : public StackVisitor {
pointer_size_(Runtime::Current()->GetClassLinker()->GetImagePointerSize()) {}
bool Init(int depth) SHARED_REQUIRES(Locks::mutator_lock_) ACQUIRE(Roles::uninterruptible_) {
- // Allocate method trace as an object array where the first element is a pointer array that
- // contains the ArtMethod pointers and dex PCs. The rest of the elements are the declaring
- // class of the ArtMethod pointers.
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- StackHandleScope<1> hs(self_);
- mirror::Class* array_class = class_linker->GetClassRoot(ClassLinker::kObjectArrayClass);
- // The first element is the methods and dex pc array, the other elements are declaring classes
- // for the methods to ensure classes in the stack trace don't get unloaded.
- Handle<mirror::ObjectArray<mirror::Object>> trace(
- hs.NewHandle(
- mirror::ObjectArray<mirror::Object>::Alloc(hs.Self(), array_class, depth + 1)));
- if (trace.Get() == nullptr) {
- // Acquire uninterruptible_ in all paths.
- self_->StartAssertNoThreadSuspension("Building internal stack trace");
- self_->AssertPendingOOMException();
- return false;
- }
- mirror::PointerArray* methods_and_pcs = class_linker->AllocPointerArray(self_, depth * 2);
+ // Allocate method trace with format [method pointers][pcs].
+ auto* cl = Runtime::Current()->GetClassLinker();
+ trace_ = cl->AllocPointerArray(self_, depth * 2);
const char* last_no_suspend_cause =
self_->StartAssertNoThreadSuspension("Building internal stack trace");
- if (methods_and_pcs == nullptr) {
+ if (trace_ == nullptr) {
self_->AssertPendingOOMException();
return false;
}
- trace->Set(0, methods_and_pcs);
- trace_ = trace.Get();
// If We are called from native, use non-transactional mode.
CHECK(last_no_suspend_cause == nullptr) << last_no_suspend_cause;
return true;
@@ -2013,24 +1996,16 @@ class BuildInternalStackTraceVisitor : public StackVisitor {
if (m->IsRuntimeMethod()) {
return true; // Ignore runtime frames (in particular callee save).
}
- mirror::PointerArray* trace_methods_and_pcs = GetTraceMethodsAndPCs();
- trace_methods_and_pcs->SetElementPtrSize<kTransactionActive>(count_, m, pointer_size_);
- trace_methods_and_pcs->SetElementPtrSize<kTransactionActive>(
- trace_methods_and_pcs->GetLength() / 2 + count_,
- m->IsProxyMethod() ? DexFile::kDexNoIndex : GetDexPc(),
- pointer_size_);
- // Save the declaring class of the method to ensure that the declaring classes of the methods
- // do not get unloaded while the stack trace is live.
- trace_->Set(count_ + 1, m->GetDeclaringClass());
+ trace_->SetElementPtrSize<kTransactionActive>(
+ count_, m, pointer_size_);
+ trace_->SetElementPtrSize<kTransactionActive>(
+ trace_->GetLength() / 2 + count_, m->IsProxyMethod() ? DexFile::kDexNoIndex : GetDexPc(),
+ pointer_size_);
++count_;
return true;
}
- mirror::PointerArray* GetTraceMethodsAndPCs() const SHARED_REQUIRES(Locks::mutator_lock_) {
- return down_cast<mirror::PointerArray*>(trace_->Get(0));
- }
-
- mirror::ObjectArray<mirror::Object>* GetInternalStackTrace() const {
+ mirror::PointerArray* GetInternalStackTrace() const {
return trace_;
}
@@ -2040,11 +2015,8 @@ class BuildInternalStackTraceVisitor : public StackVisitor {
int32_t skip_depth_;
// Current position down stack trace.
uint32_t count_;
- // An object array where the first element is a pointer array that contains the ArtMethod
- // pointers on the stack and dex PCs. The rest of the elements are the declaring
- // class of the ArtMethod pointers. trace_[i+1] contains the declaring class of the ArtMethod of
- // the i'th frame.
- mirror::ObjectArray<mirror::Object>* trace_;
+ // An array of the methods on the stack, the last entries are the dex PCs.
+ mirror::PointerArray* trace_;
// For cross compilation.
const size_t pointer_size_;
@@ -2067,12 +2039,11 @@ jobject Thread::CreateInternalStackTrace(const ScopedObjectAccessAlreadyRunnable
return nullptr; // Allocation failed.
}
build_trace_visitor.WalkStack();
- mirror::ObjectArray<mirror::Object>* trace = build_trace_visitor.GetInternalStackTrace();
+ mirror::PointerArray* trace = build_trace_visitor.GetInternalStackTrace();
if (kIsDebugBuild) {
- mirror::PointerArray* trace_methods = build_trace_visitor.GetTraceMethodsAndPCs();
- // Second half of trace_methods is dex PCs.
- for (uint32_t i = 0; i < static_cast<uint32_t>(trace_methods->GetLength() / 2); ++i) {
- auto* method = trace_methods->GetElementPtrSize<ArtMethod*>(
+ // Second half is dex PCs.
+ for (uint32_t i = 0; i < static_cast<uint32_t>(trace->GetLength() / 2); ++i) {
+ auto* method = trace->GetElementPtrSize<ArtMethod*>(
i, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
CHECK(method != nullptr);
}
@@ -2091,16 +2062,12 @@ bool Thread::IsExceptionThrownByCurrentMethod(mirror::Throwable* exception) cons
}
jobjectArray Thread::InternalStackTraceToStackTraceElementArray(
- const ScopedObjectAccessAlreadyRunnable& soa,
- jobject internal,
- jobjectArray output_array,
+ const ScopedObjectAccessAlreadyRunnable& soa, jobject internal, jobjectArray output_array,
int* stack_depth) {
- // Decode the internal stack trace into the depth, method trace and PC trace.
- // Subtract one for the methods and PC trace.
- int32_t depth = soa.Decode<mirror::Array*>(internal)->GetLength() - 1;
- DCHECK_GE(depth, 0);
+ // Decode the internal stack trace into the depth, method trace and PC trace
+ int32_t depth = soa.Decode<mirror::PointerArray*>(internal)->GetLength() / 2;
- ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+ auto* cl = Runtime::Current()->GetClassLinker();
jobjectArray result;
@@ -2114,7 +2081,7 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(
} else {
// Create java_trace array and place in local reference table
mirror::ObjectArray<mirror::StackTraceElement>* java_traces =
- class_linker->AllocStackTraceElementArray(soa.Self(), depth);
+ cl->AllocStackTraceElementArray(soa.Self(), depth);
if (java_traces == nullptr) {
return nullptr;
}
@@ -2126,12 +2093,7 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(
}
for (int32_t i = 0; i < depth; ++i) {
- mirror::ObjectArray<mirror::Object>* decoded_traces =
- soa.Decode<mirror::Object*>(internal)->AsObjectArray<mirror::Object>();
- // Methods and dex PC trace is element 0.
- DCHECK(decoded_traces->Get(0)->IsIntArray() || decoded_traces->Get(0)->IsLongArray());
- mirror::PointerArray* const method_trace =
- down_cast<mirror::PointerArray*>(decoded_traces->Get(0));
+ auto* method_trace = soa.Decode<mirror::PointerArray*>(internal);
// Prepare parameters for StackTraceElement(String cls, String method, String file, int line)
ArtMethod* method = method_trace->GetElementPtrSize<ArtMethod*>(i, sizeof(void*));
uint32_t dex_pc = method_trace->GetElementPtrSize<uint32_t>(
diff --git a/test/141-class-unload/expected.txt b/test/141-class-unload/expected.txt
index 53d7abecaf..ff65a70b12 100644
--- a/test/141-class-unload/expected.txt
+++ b/test/141-class-unload/expected.txt
@@ -16,8 +16,3 @@ loader null false
JNI_OnLoad called
JNI_OnUnload called
null
-1
-2
-JNI_OnLoad called
-class null false test
-JNI_OnUnload called
diff --git a/test/141-class-unload/src-ex/IntHolder.java b/test/141-class-unload/src-ex/IntHolder.java
index feff0d2ba1..e4aa6b8949 100644
--- a/test/141-class-unload/src-ex/IntHolder.java
+++ b/test/141-class-unload/src-ex/IntHolder.java
@@ -36,8 +36,4 @@ public class IntHolder {
}
public static native void waitForCompilation();
-
- public static Throwable generateStackTrace() {
- return new Exception("test");
- }
}
diff --git a/test/141-class-unload/src/Main.java b/test/141-class-unload/src/Main.java
index 3cc43accbe..105a2b981c 100644
--- a/test/141-class-unload/src/Main.java
+++ b/test/141-class-unload/src/Main.java
@@ -39,8 +39,6 @@ public class Main {
testNoUnloadInstance(constructor);
// Test JNI_OnLoad and JNI_OnUnload.
testLoadAndUnloadLibrary(constructor);
- // Test that stack traces keep the classes live.
- testStackTrace(constructor);
// Stress test to make sure we dont leak memory.
stressTest(constructor);
} catch (Exception e) {
@@ -77,16 +75,6 @@ public class Main {
System.out.println(loader.get());
}
- private static void testStackTrace(Constructor constructor) throws Exception {
- WeakReference<Class> klass = setUpUnloadClass(constructor);
- Method stackTraceMethod = klass.get().getDeclaredMethod("generateStackTrace");
- Throwable throwable = (Throwable) stackTraceMethod.invoke(klass.get());
- stackTraceMethod = null;
- Runtime.getRuntime().gc();
- boolean isNull = klass.get() == null;
- System.out.println("class null " + isNull + " " + throwable.getMessage());
- }
-
private static void testLoadAndUnloadLibrary(Constructor constructor) throws Exception {
WeakReference<ClassLoader> loader = setUpLoadLibrary(constructor);
// No strong refernces to class loader, should get unloaded.