Home | History | Annotate | Download | only in runtime
      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