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 "jni_internal.h" 18 19 #include <pthread.h> 20 21 #include "common_runtime_test.h" 22 #include "gc/heap.h" 23 #include "java_vm_ext.h" 24 #include "runtime.h" 25 26 namespace art { 27 28 class JavaVmExtTest : public CommonRuntimeTest { 29 protected: 30 virtual void SetUp() { 31 CommonRuntimeTest::SetUp(); 32 33 vm_ = Runtime::Current()->GetJavaVM(); 34 } 35 36 37 virtual void TearDown() OVERRIDE { 38 CommonRuntimeTest::TearDown(); 39 } 40 41 JavaVMExt* vm_; 42 }; 43 44 TEST_F(JavaVmExtTest, JNI_GetDefaultJavaVMInitArgs) { 45 jint err = JNI_GetDefaultJavaVMInitArgs(nullptr); 46 EXPECT_EQ(JNI_ERR, err); 47 } 48 49 TEST_F(JavaVmExtTest, JNI_GetCreatedJavaVMs) { 50 JavaVM* vms_buf[1]; 51 jsize num_vms; 52 jint ok = JNI_GetCreatedJavaVMs(vms_buf, arraysize(vms_buf), &num_vms); 53 EXPECT_EQ(JNI_OK, ok); 54 EXPECT_EQ(1, num_vms); 55 EXPECT_EQ(vms_buf[0], vm_); 56 } 57 58 static bool gSmallStack = false; 59 static bool gAsDaemon = false; 60 61 static void* attach_current_thread_callback(void* arg ATTRIBUTE_UNUSED) { 62 JavaVM* vms_buf[1]; 63 jsize num_vms; 64 JNIEnv* env; 65 jint ok = JNI_GetCreatedJavaVMs(vms_buf, arraysize(vms_buf), &num_vms); 66 EXPECT_EQ(JNI_OK, ok); 67 if (ok == JNI_OK) { 68 if (!gAsDaemon) { 69 ok = vms_buf[0]->AttachCurrentThread(&env, nullptr); 70 } else { 71 ok = vms_buf[0]->AttachCurrentThreadAsDaemon(&env, nullptr); 72 } 73 // TODO: Find a way to test with exact SMALL_STACK value, for which we would bail. The pthreads 74 // spec says that the stack size argument is a lower bound, and bionic currently gives us 75 // a chunk more on arm64. 76 if (!gSmallStack) { 77 EXPECT_EQ(JNI_OK, ok); 78 } 79 if (ok == JNI_OK) { 80 ok = vms_buf[0]->DetachCurrentThread(); 81 EXPECT_EQ(JNI_OK, ok); 82 } 83 } 84 return nullptr; 85 } 86 87 TEST_F(JavaVmExtTest, AttachCurrentThread) { 88 pthread_t pthread; 89 const char* reason = __PRETTY_FUNCTION__; 90 gSmallStack = false; 91 gAsDaemon = false; 92 CHECK_PTHREAD_CALL(pthread_create, (&pthread, nullptr, attach_current_thread_callback, 93 nullptr), reason); 94 void* ret_val; 95 CHECK_PTHREAD_CALL(pthread_join, (pthread, &ret_val), reason); 96 EXPECT_EQ(ret_val, nullptr); 97 } 98 99 TEST_F(JavaVmExtTest, AttachCurrentThreadAsDaemon) { 100 pthread_t pthread; 101 const char* reason = __PRETTY_FUNCTION__; 102 gSmallStack = false; 103 gAsDaemon = true; 104 CHECK_PTHREAD_CALL(pthread_create, (&pthread, nullptr, attach_current_thread_callback, 105 nullptr), reason); 106 void* ret_val; 107 CHECK_PTHREAD_CALL(pthread_join, (pthread, &ret_val), reason); 108 EXPECT_EQ(ret_val, nullptr); 109 } 110 111 TEST_F(JavaVmExtTest, AttachCurrentThread_SmallStack) { 112 pthread_t pthread; 113 pthread_attr_t attr; 114 const char* reason = __PRETTY_FUNCTION__; 115 gSmallStack = true; 116 gAsDaemon = false; 117 CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason); 118 CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, PTHREAD_STACK_MIN), reason); 119 CHECK_PTHREAD_CALL(pthread_create, (&pthread, &attr, attach_current_thread_callback, 120 nullptr), reason); 121 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason); 122 void* ret_val; 123 CHECK_PTHREAD_CALL(pthread_join, (pthread, &ret_val), reason); 124 EXPECT_EQ(ret_val, nullptr); 125 } 126 127 TEST_F(JavaVmExtTest, DetachCurrentThread) { 128 JNIEnv* env; 129 jint ok = vm_->AttachCurrentThread(&env, nullptr); 130 ASSERT_EQ(JNI_OK, ok); 131 ok = vm_->DetachCurrentThread(); 132 EXPECT_EQ(JNI_OK, ok); 133 134 jint err = vm_->DetachCurrentThread(); 135 EXPECT_EQ(JNI_ERR, err); 136 } 137 138 class JavaVmExtStackTraceTest : public JavaVmExtTest { 139 protected: 140 void SetUpRuntimeOptions(RuntimeOptions* options) OVERRIDE { 141 options->emplace_back("-XX:GlobalRefAllocStackTraceLimit=50000", nullptr); 142 } 143 }; 144 145 TEST_F(JavaVmExtStackTraceTest, TestEnableDisable) { 146 ASSERT_FALSE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()); 147 148 JNIEnv* env; 149 jint ok = vm_->AttachCurrentThread(&env, nullptr); 150 ASSERT_EQ(JNI_OK, ok); 151 152 std::vector<jobject> global_refs_; 153 jobject local_ref = env->NewStringUTF("Dummy"); 154 for (size_t i = 0; i < 2000; ++i) { 155 global_refs_.push_back(env->NewGlobalRef(local_ref)); 156 } 157 158 EXPECT_TRUE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()); 159 160 for (jobject global_ref : global_refs_) { 161 env->DeleteGlobalRef(global_ref); 162 } 163 164 EXPECT_FALSE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()); 165 166 global_refs_.clear(); 167 for (size_t i = 0; i < 2000; ++i) { 168 global_refs_.push_back(env->NewGlobalRef(local_ref)); 169 } 170 171 EXPECT_TRUE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()); 172 173 for (jobject global_ref : global_refs_) { 174 env->DeleteGlobalRef(global_ref); 175 } 176 177 EXPECT_FALSE(Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()); 178 179 ok = vm_->DetachCurrentThread(); 180 EXPECT_EQ(JNI_OK, ok); 181 } 182 183 } // namespace art 184