diff options
author | 2019-12-12 17:15:23 -0800 | |
---|---|---|
committer | 2019-12-13 23:15:02 +0000 | |
commit | b2e6d0fc6f4a7666627ab57e0f281036596d3c7f (patch) | |
tree | 0917e7e98fe735c0377ff7a9ba06818ca97bff77 | |
parent | 4847a071380288033e128986947d445e97827e5e (diff) |
Fix incorrect DCHECK
We were incorrectly asserting that the disable_pop_frame_depth field
always increased instead of that it never decreased. This meant that
we would get DCHECK failures if one caused a recursive ClassPrepare or
ClassLoad event to trigger.
Test: ./test.py --host
Bug: 146170757
Change-Id: I980a8511033fa88f3fccebb7e654336133cf33bd
-rw-r--r-- | openjdkjvmti/events-inl.h | 4 | ||||
-rw-r--r-- | test/912-classes/classes.cc | 25 | ||||
-rw-r--r-- | test/912-classes/expected.txt | 4 | ||||
-rw-r--r-- | test/912-classes/src-art/art/Test912.java | 29 |
4 files changed, 61 insertions, 1 deletions
diff --git a/openjdkjvmti/events-inl.h b/openjdkjvmti/events-inl.h index 23f7151c99..883a4ccfd8 100644 --- a/openjdkjvmti/events-inl.h +++ b/openjdkjvmti/events-inl.h @@ -453,8 +453,10 @@ struct ScopedDisablePopFrame { thread_, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames); old_disable_frame_pop_depth_ = data->disable_pop_frame_depth; data->disable_pop_frame_depth = current_top_frame_; + // Check that we cleaned up any old disables. This should only increase (or be equals if we do + // another ClassLoad/Prepare recursively). DCHECK(old_disable_frame_pop_depth_ == JvmtiGlobalTLSData::kNoDisallowedPopFrame || - current_top_frame_ > old_disable_frame_pop_depth_) + current_top_frame_ >= old_disable_frame_pop_depth_) << "old: " << old_disable_frame_pop_depth_ << " current: " << current_top_frame_; } diff --git a/test/912-classes/classes.cc b/test/912-classes/classes.cc index 1f6954ef99..5032762f71 100644 --- a/test/912-classes/classes.cc +++ b/test/912-classes/classes.cc @@ -596,5 +596,30 @@ extern "C" JNIEXPORT void JNICALL Java_art_Test912_enableClassLoadPrepareEqualit } } +static jobject gRunnableGlobal = nullptr; +extern "C" JNIEXPORT void JNICALL Java_art_Test912_runRecursiveClassPrepareEvents( + JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject runnable) { + CHECK(gRunnableGlobal == nullptr); + gRunnableGlobal = env->NewGlobalRef(runnable); + EnableEvents( + env, + true, + nullptr, + [](jvmtiEnv* jenv ATTRIBUTE_UNUSED, + JNIEnv* jni_env, + jthread thread ATTRIBUTE_UNUSED, + jclass klass ATTRIBUTE_UNUSED) -> void { + jclass runnable_class = jni_env->FindClass("java/lang/Runnable"); + jni_env->CallVoidMethod( + gRunnableGlobal, jni_env->GetMethodID(runnable_class, "run", "()V")); + }); + jclass runnable_class = env->FindClass("java/lang/Runnable"); + env->CallVoidMethod( + runnable, env->GetMethodID(runnable_class, "run", "()V")); + EnableEvents(env, false, nullptr, nullptr); + env->DeleteGlobalRef(gRunnableGlobal); + gRunnableGlobal = nullptr; +} + } // namespace Test912Classes } // namespace art diff --git a/test/912-classes/expected.txt b/test/912-classes/expected.txt index 7ad5d608b7..d7699b6278 100644 --- a/test/912-classes/expected.txt +++ b/test/912-classes/expected.txt @@ -91,3 +91,7 @@ Load: L$Proxy21; on ClassEvents Prepare: L$Proxy21; on ClassEvents (cur=ClassEvents) Load: [Lart/Test912; on ClassEvents Prepare: [Lart/Test912; on ClassEvents (cur=ClassEvents) +class-prepare event START! +class-prepare event START! +class-prepare event END! +class-prepare event END! diff --git a/test/912-classes/src-art/art/Test912.java b/test/912-classes/src-art/art/Test912.java index 1a60185f49..a2e89345b5 100644 --- a/test/912-classes/src-art/art/Test912.java +++ b/test/912-classes/src-art/art/Test912.java @@ -105,6 +105,9 @@ public class Test912 { }; classEventsThread.start(); classEventsThread.join(); + + // b/146170757 + TestRecursiveClassPrepareEvents(); } private static void testClass(String className) throws Exception { @@ -394,6 +397,32 @@ public class Test912 { private static native void setEqualityEventStorageClass(Class<?> c); private static native void enableClassLoadPrepareEqualityEvents(boolean b); + private static native void runRecursiveClassPrepareEvents(Runnable forceLoad); + + private static void TestRecursiveClassPrepareEvents() { + final int[] called = new int[] { 0 }; + runRecursiveClassPrepareEvents(() -> { + if (called[0] == 2) { + return; + } else { + called[0]++; + } + try { + System.out.println("class-prepare event START!"); + // Load a new class in a new class-loader. + Class<?> class_loader_class = Class.forName("dalvik.system.InMemoryDexClassLoader"); + Constructor<?> ctor = class_loader_class.getConstructor(ByteBuffer.class, ClassLoader.class); + Class<?> target = ((ClassLoader)ctor.newInstance( + ByteBuffer.wrap(DEX_BYTES), Test912.class.getClassLoader())).loadClass("Transform"); + target.newInstance(); + } catch (Exception e) { } + System.out.println("class-prepare event END!"); + }); + if (called[0] != 2) { + System.out.println("Failed to cause recursive Class prepare."); + } + } + private static class TestForNonInit { public static double dummy = Math.random(); // So it can't be compile-time initialized. } |