You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
5.2 KiB
185 lines
5.2 KiB
/*
|
|
* Copyright (C) 2011 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "jni/jni_internal.h"
|
|
|
|
#include <pthread.h>
|
|
|
|
#include "common_runtime_test.h"
|
|
#include "gc/heap.h"
|
|
#include "java_vm_ext.h"
|
|
#include "runtime.h"
|
|
|
|
namespace art {
|
|
|
|
class JavaVmExtTest : public CommonRuntimeTest {
|
|
protected:
|
|
void SetUp() override {
|
|
CommonRuntimeTest::SetUp();
|
|
|
|
vm_ = Runtime::Current()->GetJavaVM();
|
|
}
|
|
|
|
|
|
void TearDown() override {
|
|
CommonRuntimeTest::TearDown();
|
|
}
|
|
|
|
JavaVMExt* vm_;
|
|
};
|
|
|
|
TEST_F(JavaVmExtTest, JNI_GetDefaultJavaVMInitArgs) {
|
|
jint err = JNI_GetDefaultJavaVMInitArgs(nullptr);
|
|
EXPECT_EQ(JNI_ERR, err);
|
|
}
|
|
|
|
TEST_F(JavaVmExtTest, JNI_GetCreatedJavaVMs) {
|
|
JavaVM* vms_buf[1];
|
|
jsize num_vms;
|
|
jint ok = JNI_GetCreatedJavaVMs(vms_buf, arraysize(vms_buf), &num_vms);
|
|
EXPECT_EQ(JNI_OK, ok);
|
|
EXPECT_EQ(1, num_vms);
|
|
EXPECT_EQ(vms_buf[0], vm_);
|
|
}
|
|
|
|
static bool gSmallStack = false;
|
|
static bool gAsDaemon = false;
|
|
|
|
static void* attach_current_thread_callback(void* arg ATTRIBUTE_UNUSED) {
|
|
JavaVM* vms_buf[1];
|
|
jsize num_vms;
|
|
JNIEnv* env;
|
|
jint ok = JNI_GetCreatedJavaVMs(vms_buf, arraysize(vms_buf), &num_vms);
|
|
EXPECT_EQ(JNI_OK, ok);
|
|
if (ok == JNI_OK) {
|
|
if (!gAsDaemon) {
|
|
ok = vms_buf[0]->AttachCurrentThread(&env, nullptr);
|
|
} else {
|
|
ok = vms_buf[0]->AttachCurrentThreadAsDaemon(&env, nullptr);
|
|
}
|
|
// TODO: Find a way to test with exact SMALL_STACK value, for which we would bail. The pthreads
|
|
// spec says that the stack size argument is a lower bound, and bionic currently gives us
|
|
// a chunk more on arm64.
|
|
if (!gSmallStack) {
|
|
EXPECT_EQ(JNI_OK, ok);
|
|
}
|
|
if (ok == JNI_OK) {
|
|
ok = vms_buf[0]->DetachCurrentThread();
|
|
EXPECT_EQ(JNI_OK, ok);
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
TEST_F(JavaVmExtTest, AttachCurrentThread) {
|
|
pthread_t pthread;
|
|
const char* reason = __PRETTY_FUNCTION__;
|
|
gSmallStack = false;
|
|
gAsDaemon = false;
|
|
CHECK_PTHREAD_CALL(pthread_create, (&pthread, nullptr, attach_current_thread_callback,
|
|
nullptr), reason);
|
|
void* ret_val;
|
|
CHECK_PTHREAD_CALL(pthread_join, (pthread, &ret_val), reason);
|
|
EXPECT_EQ(ret_val, nullptr);
|
|
}
|
|
|
|
TEST_F(JavaVmExtTest, AttachCurrentThreadAsDaemon) {
|
|
pthread_t pthread;
|
|
const char* reason = __PRETTY_FUNCTION__;
|
|
gSmallStack = false;
|
|
gAsDaemon = true;
|
|
CHECK_PTHREAD_CALL(pthread_create, (&pthread, nullptr, attach_current_thread_callback,
|
|
nullptr), reason);
|
|
void* ret_val;
|
|
CHECK_PTHREAD_CALL(pthread_join, (pthread, &ret_val), reason);
|
|
EXPECT_EQ(ret_val, nullptr);
|
|
}
|
|
|
|
TEST_F(JavaVmExtTest, AttachCurrentThread_SmallStack) {
|
|
TEST_DISABLED_FOR_MEMORY_TOOL(); // b/123500163
|
|
pthread_t pthread;
|
|
pthread_attr_t attr;
|
|
const char* reason = __PRETTY_FUNCTION__;
|
|
gSmallStack = true;
|
|
gAsDaemon = false;
|
|
CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
|
|
CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, PTHREAD_STACK_MIN), reason);
|
|
CHECK_PTHREAD_CALL(pthread_create, (&pthread, &attr, attach_current_thread_callback,
|
|
nullptr), reason);
|
|
CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
|
|
void* ret_val;
|
|
CHECK_PTHREAD_CALL(pthread_join, (pthread, &ret_val), reason);
|
|
EXPECT_EQ(ret_val, nullptr);
|
|
}
|
|
|
|
TEST_F(JavaVmExtTest, DetachCurrentThread) {
|
|
JNIEnv* env;
|
|
jint ok = vm_->AttachCurrentThread(&env, nullptr);
|
|
ASSERT_EQ(JNI_OK, ok);
|
|
ok = vm_->DetachCurrentThread();
|
|
EXPECT_EQ(JNI_OK, ok);
|
|
|
|
jint err = vm_->DetachCurrentThread();
|
|
EXPECT_EQ(JNI_ERR, err);
|
|
}
|
|
|
|
class JavaVmExtStackTraceTest : public JavaVmExtTest {
|
|
protected:
|
|
void SetUpRuntimeOptions(RuntimeOptions* options) override {
|
|
options->emplace_back("-XX:GlobalRefAllocStackTraceLimit=50000", nullptr);
|
|
}
|
|
};
|
|
|
|
TEST_F(JavaVmExtStackTraceTest, TestEnableDisable) {
|
|
ASSERT_FALSE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
|
|
|
|
JNIEnv* env;
|
|
jint ok = vm_->AttachCurrentThread(&env, nullptr);
|
|
ASSERT_EQ(JNI_OK, ok);
|
|
|
|
std::vector<jobject> global_refs_;
|
|
jobject local_ref = env->NewStringUTF("Hello");
|
|
for (size_t i = 0; i < 2000; ++i) {
|
|
global_refs_.push_back(env->NewGlobalRef(local_ref));
|
|
}
|
|
|
|
EXPECT_TRUE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
|
|
|
|
for (jobject global_ref : global_refs_) {
|
|
env->DeleteGlobalRef(global_ref);
|
|
}
|
|
|
|
EXPECT_FALSE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
|
|
|
|
global_refs_.clear();
|
|
for (size_t i = 0; i < 2000; ++i) {
|
|
global_refs_.push_back(env->NewGlobalRef(local_ref));
|
|
}
|
|
|
|
EXPECT_TRUE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
|
|
|
|
for (jobject global_ref : global_refs_) {
|
|
env->DeleteGlobalRef(global_ref);
|
|
}
|
|
|
|
EXPECT_FALSE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
|
|
|
|
ok = vm_->DetachCurrentThread();
|
|
EXPECT_EQ(JNI_OK, ok);
|
|
}
|
|
|
|
} // namespace art
|