summaryrefslogtreecommitdiff
path: root/test/178-app-image-native-method/native_methods.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/178-app-image-native-method/native_methods.cc')
-rw-r--r--test/178-app-image-native-method/native_methods.cc64
1 files changed, 64 insertions, 0 deletions
diff --git a/test/178-app-image-native-method/native_methods.cc b/test/178-app-image-native-method/native_methods.cc
index 0669deb4b3..709c5dfe64 100644
--- a/test/178-app-image-native-method/native_methods.cc
+++ b/test/178-app-image-native-method/native_methods.cc
@@ -14,8 +14,16 @@
* limitations under the License.
*/
+#include <sstream>
+
#include "jni.h"
+#include "arch/context.h"
+#include "monitor.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread-current-inl.h"
+
namespace art {
static inline bool VerifyManyParameters(
@@ -638,4 +646,60 @@ extern "C" JNIEXPORT jint JNICALL Java_CriticalClinitCheck_nativeMethodWithManyP
return ok ? 42 : -1;
}
+extern "C" JNIEXPORT jint JNICALL Java_Main_b189235039CallThrough(JNIEnv* env, jobject m) {
+ jclass main_klass = env->GetObjectClass(m);
+ jmethodID checkLocks = env->GetStaticMethodID(main_klass, "b189235039CheckLocks", "(ILMain;)I");
+ if (checkLocks == nullptr) {
+ return -1;
+ }
+ return env->CallStaticIntMethod(main_klass, checkLocks, 42, m);
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_b189235039CheckLocks(JNIEnv*,
+ jclass,
+ int arg,
+ jobject lock) {
+ // Check that we do not crash when visiting locks and that we find the right lock.
+ ScopedObjectAccess soa(Thread::Current());
+ class VisitLocks : public StackVisitor {
+ public:
+ VisitLocks(Thread* thread, Context* context, jobject expected_lock)
+ : StackVisitor(thread, context, StackWalkKind::kIncludeInlinedFrames),
+ expected_lock_(expected_lock) {
+ }
+
+ bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* m = GetMethod();
+
+ // Ignore runtime methods.
+ if (m == nullptr || m->IsRuntimeMethod()) {
+ return true;
+ }
+
+ if (m->IsSynchronized()) {
+ // Interesting frame.
+ Monitor::VisitLocks(this, Callback, expected_lock_);
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ static void Callback(ObjPtr<mirror::Object> obj, void* expected_lock)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ CHECK(obj != nullptr);
+ CHECK(obj == Thread::Current()->DecodeJObject(reinterpret_cast<jobject>(expected_lock)));
+ }
+
+ jobject expected_lock_;
+ };
+ {
+ std::unique_ptr<Context> context(Context::Create());
+ VisitLocks vl(soa.Self(), context.get(), lock);
+ vl.WalkStack();
+ }
+ return arg;
+}
+
} // namespace art