• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "class_linker.h"
18 #include "common_test.h"
19 #include "dex_file.h"
20 #include "gtest/gtest.h"
21 #include "indirect_reference_table.h"
22 #include "jni_internal.h"
23 #include "mem_map.h"
24 #include "mirror/art_method-inl.h"
25 #include "mirror/class-inl.h"
26 #include "mirror/class_loader.h"
27 #include "mirror/object_array-inl.h"
28 #include "mirror/object-inl.h"
29 #include "mirror/stack_trace_element.h"
30 #include "runtime.h"
31 #include "ScopedLocalRef.h"
32 #include "scoped_thread_state_change.h"
33 #include "thread.h"
34 #include "UniquePtr.h"
35 
Java_MyClassNatives_bar(JNIEnv *,jobject,jint count)36 extern "C" JNIEXPORT jint JNICALL Java_MyClassNatives_bar(JNIEnv*, jobject, jint count) {
37   return count + 1;
38 }
39 
Java_MyClassNatives_sbar(JNIEnv *,jclass,jint count)40 extern "C" JNIEXPORT jint JNICALL Java_MyClassNatives_sbar(JNIEnv*, jclass, jint count) {
41   return count + 1;
42 }
43 
44 namespace art {
45 
46 class JniCompilerTest : public CommonTest {
47  protected:
CompileForTest(jobject class_loader,bool direct,const char * method_name,const char * method_sig)48   void CompileForTest(jobject class_loader, bool direct,
49                       const char* method_name, const char* method_sig) {
50     ScopedObjectAccess soa(Thread::Current());
51     // Compile the native method before starting the runtime
52     mirror::Class* c = class_linker_->FindClass("LMyClassNatives;",
53                                                 soa.Decode<mirror::ClassLoader*>(class_loader));
54     mirror::ArtMethod* method;
55     if (direct) {
56       method = c->FindDirectMethod(method_name, method_sig);
57     } else {
58       method = c->FindVirtualMethod(method_name, method_sig);
59     }
60     ASSERT_TRUE(method != NULL) << method_name << " " << method_sig;
61     if (method->GetEntryPointFromCompiledCode() != NULL) {
62       return;
63     }
64     CompileMethod(method);
65     ASSERT_TRUE(method->GetEntryPointFromCompiledCode() != NULL) << method_name << " " << method_sig;
66   }
67 
SetUpForTest(bool direct,const char * method_name,const char * method_sig,void * native_fnptr)68   void SetUpForTest(bool direct, const char* method_name, const char* method_sig,
69                     void* native_fnptr) {
70     // Initialize class loader and compile method when runtime not started.
71     if (!runtime_->IsStarted()) {
72       {
73         ScopedObjectAccess soa(Thread::Current());
74         class_loader_ = LoadDex("MyClassNatives");
75       }
76       CompileForTest(class_loader_, direct, method_name, method_sig);
77       // Start runtime.
78       Thread::Current()->TransitionFromSuspendedToRunnable();
79       bool started = runtime_->Start();
80       CHECK(started);
81     }
82     // JNI operations after runtime start.
83     env_ = Thread::Current()->GetJniEnv();
84     jklass_ = env_->FindClass("MyClassNatives");
85     ASSERT_TRUE(jklass_ != NULL) << method_name << " " << method_sig;
86 
87     if (direct) {
88       jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
89     } else {
90       jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
91     }
92     ASSERT_TRUE(jmethod_ != NULL) << method_name << " " << method_sig;
93 
94     if (native_fnptr != NULL) {
95       JNINativeMethod methods[] = { { method_name, method_sig, native_fnptr } };
96       ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1))
97               << method_name << " " << method_sig;
98     } else {
99       env_->UnregisterNatives(jklass_);
100     }
101 
102     jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
103     jobj_ = env_->NewObject(jklass_, constructor);
104     ASSERT_TRUE(jobj_ != NULL) << method_name << " " << method_sig;
105   }
106 
107  public:
108   static jclass jklass_;
109   static jobject jobj_;
110   static jobject class_loader_;
111 
112 
113  protected:
114   JNIEnv* env_;
115   jmethodID jmethod_;
116 };
117 
118 jclass JniCompilerTest::jklass_;
119 jobject JniCompilerTest::jobj_;
120 jobject JniCompilerTest::class_loader_;
121 
122 int gJava_MyClassNatives_foo_calls = 0;
Java_MyClassNatives_foo(JNIEnv * env,jobject thisObj)123 void Java_MyClassNatives_foo(JNIEnv* env, jobject thisObj) {
124   // 1 = thisObj
125   EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
126   EXPECT_EQ(kNative, Thread::Current()->GetState());
127   Locks::mutator_lock_->AssertNotHeld(Thread::Current());
128   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
129   EXPECT_TRUE(thisObj != NULL);
130   EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
131   gJava_MyClassNatives_foo_calls++;
132 }
133 
TEST_F(JniCompilerTest,CompileAndRunNoArgMethod)134 TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
135   TEST_DISABLED_FOR_PORTABLE();
136   SetUpForTest(false, "foo", "()V",
137                reinterpret_cast<void*>(&Java_MyClassNatives_foo));
138 
139   EXPECT_EQ(0, gJava_MyClassNatives_foo_calls);
140   env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
141   EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
142   env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
143   EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
144 }
145 
TEST_F(JniCompilerTest,CompileAndRunIntMethodThroughStub)146 TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
147   TEST_DISABLED_FOR_PORTABLE();
148   SetUpForTest(false, "bar", "(I)I",
149                NULL /* calling through stub will link with &Java_MyClassNatives_bar */);
150 
151   ScopedObjectAccess soa(Thread::Current());
152   std::string reason;
153   ASSERT_TRUE(
154       Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<mirror::ClassLoader*>(class_loader_),
155                                                          reason)) << reason;
156 
157   jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
158   EXPECT_EQ(25, result);
159 }
160 
TEST_F(JniCompilerTest,CompileAndRunStaticIntMethodThroughStub)161 TEST_F(JniCompilerTest, CompileAndRunStaticIntMethodThroughStub) {
162   TEST_DISABLED_FOR_PORTABLE();
163   SetUpForTest(true, "sbar", "(I)I",
164                NULL /* calling through stub will link with &Java_MyClassNatives_sbar */);
165 
166   ScopedObjectAccess soa(Thread::Current());
167   std::string reason;
168   ASSERT_TRUE(
169       Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<mirror::ClassLoader*>(class_loader_),
170                                                          reason)) << reason;
171 
172   jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42);
173   EXPECT_EQ(43, result);
174 }
175 
176 int gJava_MyClassNatives_fooI_calls = 0;
Java_MyClassNatives_fooI(JNIEnv * env,jobject thisObj,jint x)177 jint Java_MyClassNatives_fooI(JNIEnv* env, jobject thisObj, jint x) {
178   // 1 = thisObj
179   EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
180   EXPECT_EQ(kNative, Thread::Current()->GetState());
181   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
182   EXPECT_TRUE(thisObj != NULL);
183   EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
184   gJava_MyClassNatives_fooI_calls++;
185   return x;
186 }
187 
TEST_F(JniCompilerTest,CompileAndRunIntMethod)188 TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
189   TEST_DISABLED_FOR_PORTABLE();
190   SetUpForTest(false, "fooI", "(I)I",
191                reinterpret_cast<void*>(&Java_MyClassNatives_fooI));
192 
193   EXPECT_EQ(0, gJava_MyClassNatives_fooI_calls);
194   jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
195   EXPECT_EQ(42, result);
196   EXPECT_EQ(1, gJava_MyClassNatives_fooI_calls);
197   result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
198   EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
199   EXPECT_EQ(2, gJava_MyClassNatives_fooI_calls);
200 }
201 
202 int gJava_MyClassNatives_fooII_calls = 0;
Java_MyClassNatives_fooII(JNIEnv * env,jobject thisObj,jint x,jint y)203 jint Java_MyClassNatives_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
204   // 1 = thisObj
205   EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
206   EXPECT_EQ(kNative, Thread::Current()->GetState());
207   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
208   EXPECT_TRUE(thisObj != NULL);
209   EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
210   gJava_MyClassNatives_fooII_calls++;
211   return x - y;  // non-commutative operator
212 }
213 
TEST_F(JniCompilerTest,CompileAndRunIntIntMethod)214 TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
215   TEST_DISABLED_FOR_PORTABLE();
216   SetUpForTest(false, "fooII", "(II)I",
217                reinterpret_cast<void*>(&Java_MyClassNatives_fooII));
218 
219   EXPECT_EQ(0, gJava_MyClassNatives_fooII_calls);
220   jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
221   EXPECT_EQ(99 - 10, result);
222   EXPECT_EQ(1, gJava_MyClassNatives_fooII_calls);
223   result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
224                                          0xCAFED00D);
225   EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
226   EXPECT_EQ(2, gJava_MyClassNatives_fooII_calls);
227 }
228 
229 int gJava_MyClassNatives_fooJJ_calls = 0;
Java_MyClassNatives_fooJJ(JNIEnv * env,jobject thisObj,jlong x,jlong y)230 jlong Java_MyClassNatives_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
231   // 1 = thisObj
232   EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
233   EXPECT_EQ(kNative, Thread::Current()->GetState());
234   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
235   EXPECT_TRUE(thisObj != NULL);
236   EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
237   gJava_MyClassNatives_fooJJ_calls++;
238   return x - y;  // non-commutative operator
239 }
240 
TEST_F(JniCompilerTest,CompileAndRunLongLongMethod)241 TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
242   TEST_DISABLED_FOR_PORTABLE();
243   SetUpForTest(false, "fooJJ", "(JJ)J",
244                reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ));
245 
246   EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_calls);
247   jlong a = 0x1234567890ABCDEFll;
248   jlong b = 0xFEDCBA0987654321ll;
249   jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
250   EXPECT_EQ(a - b, result);
251   EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_calls);
252   result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
253   EXPECT_EQ(b - a, result);
254   EXPECT_EQ(2, gJava_MyClassNatives_fooJJ_calls);
255 }
256 
257 int gJava_MyClassNatives_fooDD_calls = 0;
Java_MyClassNatives_fooDD(JNIEnv * env,jobject thisObj,jdouble x,jdouble y)258 jdouble Java_MyClassNatives_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
259   // 1 = thisObj
260   EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
261   EXPECT_EQ(kNative, Thread::Current()->GetState());
262   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
263   EXPECT_TRUE(thisObj != NULL);
264   EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
265   gJava_MyClassNatives_fooDD_calls++;
266   return x - y;  // non-commutative operator
267 }
268 
TEST_F(JniCompilerTest,CompileAndRunDoubleDoubleMethod)269 TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
270   TEST_DISABLED_FOR_PORTABLE();
271   SetUpForTest(false, "fooDD", "(DD)D",
272                reinterpret_cast<void*>(&Java_MyClassNatives_fooDD));
273 
274   EXPECT_EQ(0, gJava_MyClassNatives_fooDD_calls);
275   jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
276                                                     99.0, 10.0);
277   EXPECT_EQ(99.0 - 10.0, result);
278   EXPECT_EQ(1, gJava_MyClassNatives_fooDD_calls);
279   jdouble a = 3.14159265358979323846;
280   jdouble b = 0.69314718055994530942;
281   result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
282   EXPECT_EQ(a - b, result);
283   EXPECT_EQ(2, gJava_MyClassNatives_fooDD_calls);
284 }
285 
286 int gJava_MyClassNatives_fooJJ_synchronized_calls = 0;
Java_MyClassNatives_fooJJ_synchronized(JNIEnv * env,jobject thisObj,jlong x,jlong y)287 jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
288   // 1 = thisObj
289   EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
290   EXPECT_EQ(kNative, Thread::Current()->GetState());
291   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
292   EXPECT_TRUE(thisObj != NULL);
293   EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
294   gJava_MyClassNatives_fooJJ_synchronized_calls++;
295   return x | y;
296 }
297 
TEST_F(JniCompilerTest,CompileAndRun_fooJJ_synchronized)298 TEST_F(JniCompilerTest, CompileAndRun_fooJJ_synchronized) {
299   TEST_DISABLED_FOR_PORTABLE();
300   SetUpForTest(false, "fooJJ_synchronized", "(JJ)J",
301                reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ_synchronized));
302 
303   EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_synchronized_calls);
304   jlong a = 0x1000000020000000ULL;
305   jlong b = 0x00ff000000aa0000ULL;
306   jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
307   EXPECT_EQ(a | b, result);
308   EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_synchronized_calls);
309 }
310 
311 int gJava_MyClassNatives_fooIOO_calls = 0;
Java_MyClassNatives_fooIOO(JNIEnv * env,jobject thisObj,jint x,jobject y,jobject z)312 jobject Java_MyClassNatives_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
313                             jobject z) {
314   // 3 = this + y + z
315   EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
316   EXPECT_EQ(kNative, Thread::Current()->GetState());
317   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
318   EXPECT_TRUE(thisObj != NULL);
319   EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
320   gJava_MyClassNatives_fooIOO_calls++;
321   switch (x) {
322     case 1:
323       return y;
324     case 2:
325       return z;
326     default:
327       return thisObj;
328   }
329 }
330 
TEST_F(JniCompilerTest,CompileAndRunIntObjectObjectMethod)331 TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
332   TEST_DISABLED_FOR_PORTABLE();
333   SetUpForTest(false, "fooIOO",
334                "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
335                reinterpret_cast<void*>(&Java_MyClassNatives_fooIOO));
336 
337   EXPECT_EQ(0, gJava_MyClassNatives_fooIOO_calls);
338   jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
339   EXPECT_TRUE(env_->IsSameObject(jobj_, result));
340   EXPECT_EQ(1, gJava_MyClassNatives_fooIOO_calls);
341 
342   result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
343   EXPECT_TRUE(env_->IsSameObject(jobj_, result));
344   EXPECT_EQ(2, gJava_MyClassNatives_fooIOO_calls);
345   result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
346   EXPECT_TRUE(env_->IsSameObject(NULL, result));
347   EXPECT_EQ(3, gJava_MyClassNatives_fooIOO_calls);
348   result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
349   EXPECT_TRUE(env_->IsSameObject(jklass_, result));
350   EXPECT_EQ(4, gJava_MyClassNatives_fooIOO_calls);
351 
352   result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
353   EXPECT_TRUE(env_->IsSameObject(jobj_, result));
354   EXPECT_EQ(5, gJava_MyClassNatives_fooIOO_calls);
355   result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
356   EXPECT_TRUE(env_->IsSameObject(jklass_, result));
357   EXPECT_EQ(6, gJava_MyClassNatives_fooIOO_calls);
358   result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
359   EXPECT_TRUE(env_->IsSameObject(NULL, result));
360   EXPECT_EQ(7, gJava_MyClassNatives_fooIOO_calls);
361 }
362 
363 int gJava_MyClassNatives_fooSII_calls = 0;
Java_MyClassNatives_fooSII(JNIEnv * env,jclass klass,jint x,jint y)364 jint Java_MyClassNatives_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
365   // 1 = klass
366   EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
367   EXPECT_EQ(kNative, Thread::Current()->GetState());
368   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
369   EXPECT_TRUE(klass != NULL);
370   EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
371   gJava_MyClassNatives_fooSII_calls++;
372   return x + y;
373 }
374 
TEST_F(JniCompilerTest,CompileAndRunStaticIntIntMethod)375 TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
376   TEST_DISABLED_FOR_PORTABLE();
377   SetUpForTest(true, "fooSII", "(II)I",
378                reinterpret_cast<void*>(&Java_MyClassNatives_fooSII));
379 
380   EXPECT_EQ(0, gJava_MyClassNatives_fooSII_calls);
381   jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
382   EXPECT_EQ(50, result);
383   EXPECT_EQ(1, gJava_MyClassNatives_fooSII_calls);
384 }
385 
386 int gJava_MyClassNatives_fooSDD_calls = 0;
Java_MyClassNatives_fooSDD(JNIEnv * env,jclass klass,jdouble x,jdouble y)387 jdouble Java_MyClassNatives_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
388   // 1 = klass
389   EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
390   EXPECT_EQ(kNative, Thread::Current()->GetState());
391   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
392   EXPECT_TRUE(klass != NULL);
393   EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
394   gJava_MyClassNatives_fooSDD_calls++;
395   return x - y;  // non-commutative operator
396 }
397 
TEST_F(JniCompilerTest,CompileAndRunStaticDoubleDoubleMethod)398 TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
399   TEST_DISABLED_FOR_PORTABLE();
400   SetUpForTest(true, "fooSDD", "(DD)D",
401                reinterpret_cast<void*>(&Java_MyClassNatives_fooSDD));
402 
403   EXPECT_EQ(0, gJava_MyClassNatives_fooSDD_calls);
404   jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
405   EXPECT_EQ(99.0 - 10.0, result);
406   EXPECT_EQ(1, gJava_MyClassNatives_fooSDD_calls);
407   jdouble a = 3.14159265358979323846;
408   jdouble b = 0.69314718055994530942;
409   result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
410   EXPECT_EQ(a - b, result);
411   EXPECT_EQ(2, gJava_MyClassNatives_fooSDD_calls);
412 }
413 
414 int gJava_MyClassNatives_fooSIOO_calls = 0;
Java_MyClassNatives_fooSIOO(JNIEnv * env,jclass klass,jint x,jobject y,jobject z)415 jobject Java_MyClassNatives_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
416                              jobject z) {
417   // 3 = klass + y + z
418   EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
419   EXPECT_EQ(kNative, Thread::Current()->GetState());
420   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
421   EXPECT_TRUE(klass != NULL);
422   EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
423   gJava_MyClassNatives_fooSIOO_calls++;
424   switch (x) {
425     case 1:
426       return y;
427     case 2:
428       return z;
429     default:
430       return klass;
431   }
432 }
433 
434 
TEST_F(JniCompilerTest,CompileAndRunStaticIntObjectObjectMethod)435 TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
436   TEST_DISABLED_FOR_PORTABLE();
437   SetUpForTest(true, "fooSIOO",
438                "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
439                reinterpret_cast<void*>(&Java_MyClassNatives_fooSIOO));
440 
441   EXPECT_EQ(0, gJava_MyClassNatives_fooSIOO_calls);
442   jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
443   EXPECT_TRUE(env_->IsSameObject(jklass_, result));
444   EXPECT_EQ(1, gJava_MyClassNatives_fooSIOO_calls);
445 
446   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
447   EXPECT_TRUE(env_->IsSameObject(jklass_, result));
448   EXPECT_EQ(2, gJava_MyClassNatives_fooSIOO_calls);
449   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
450   EXPECT_TRUE(env_->IsSameObject(NULL, result));
451   EXPECT_EQ(3, gJava_MyClassNatives_fooSIOO_calls);
452   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
453   EXPECT_TRUE(env_->IsSameObject(jobj_, result));
454   EXPECT_EQ(4, gJava_MyClassNatives_fooSIOO_calls);
455 
456   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
457   EXPECT_TRUE(env_->IsSameObject(jklass_, result));
458   EXPECT_EQ(5, gJava_MyClassNatives_fooSIOO_calls);
459   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
460   EXPECT_TRUE(env_->IsSameObject(jobj_, result));
461   EXPECT_EQ(6, gJava_MyClassNatives_fooSIOO_calls);
462   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
463   EXPECT_TRUE(env_->IsSameObject(NULL, result));
464   EXPECT_EQ(7, gJava_MyClassNatives_fooSIOO_calls);
465 }
466 
467 int gJava_MyClassNatives_fooSSIOO_calls = 0;
Java_MyClassNatives_fooSSIOO(JNIEnv * env,jclass klass,jint x,jobject y,jobject z)468 jobject Java_MyClassNatives_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y, jobject z) {
469   // 3 = klass + y + z
470   EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
471   EXPECT_EQ(kNative, Thread::Current()->GetState());
472   EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
473   EXPECT_TRUE(klass != NULL);
474   EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
475   gJava_MyClassNatives_fooSSIOO_calls++;
476   switch (x) {
477     case 1:
478       return y;
479     case 2:
480       return z;
481     default:
482       return klass;
483   }
484 }
485 
TEST_F(JniCompilerTest,CompileAndRunStaticSynchronizedIntObjectObjectMethod)486 TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
487   TEST_DISABLED_FOR_PORTABLE();
488   SetUpForTest(true, "fooSSIOO",
489                "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
490                reinterpret_cast<void*>(&Java_MyClassNatives_fooSSIOO));
491 
492   EXPECT_EQ(0, gJava_MyClassNatives_fooSSIOO_calls);
493   jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
494   EXPECT_TRUE(env_->IsSameObject(jklass_, result));
495   EXPECT_EQ(1, gJava_MyClassNatives_fooSSIOO_calls);
496 
497   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
498   EXPECT_TRUE(env_->IsSameObject(jklass_, result));
499   EXPECT_EQ(2, gJava_MyClassNatives_fooSSIOO_calls);
500   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
501   EXPECT_TRUE(env_->IsSameObject(NULL, result));
502   EXPECT_EQ(3, gJava_MyClassNatives_fooSSIOO_calls);
503   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
504   EXPECT_TRUE(env_->IsSameObject(jobj_, result));
505   EXPECT_EQ(4, gJava_MyClassNatives_fooSSIOO_calls);
506 
507   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
508   EXPECT_TRUE(env_->IsSameObject(jklass_, result));
509   EXPECT_EQ(5, gJava_MyClassNatives_fooSSIOO_calls);
510   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
511   EXPECT_TRUE(env_->IsSameObject(jobj_, result));
512   EXPECT_EQ(6, gJava_MyClassNatives_fooSSIOO_calls);
513   result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
514   EXPECT_TRUE(env_->IsSameObject(NULL, result));
515   EXPECT_EQ(7, gJava_MyClassNatives_fooSSIOO_calls);
516 }
517 
Java_MyClassNatives_throwException(JNIEnv * env,jobject)518 void Java_MyClassNatives_throwException(JNIEnv* env, jobject) {
519   jclass c = env->FindClass("java/lang/RuntimeException");
520   env->ThrowNew(c, "hello");
521 }
522 
TEST_F(JniCompilerTest,ExceptionHandling)523 TEST_F(JniCompilerTest, ExceptionHandling) {
524   TEST_DISABLED_FOR_PORTABLE();
525   {
526     ASSERT_FALSE(runtime_->IsStarted());
527     ScopedObjectAccess soa(Thread::Current());
528     class_loader_ = LoadDex("MyClassNatives");
529 
530     // all compilation needs to happen before Runtime::Start
531     CompileForTest(class_loader_, false, "foo", "()V");
532     CompileForTest(class_loader_, false, "throwException", "()V");
533     CompileForTest(class_loader_, false, "foo", "()V");
534   }
535   // Start runtime to avoid re-initialization in SetupForTest.
536   Thread::Current()->TransitionFromSuspendedToRunnable();
537   bool started = runtime_->Start();
538   CHECK(started);
539 
540   gJava_MyClassNatives_foo_calls = 0;
541 
542   // Check a single call of a JNI method is ok
543   SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
544   env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
545   EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
546   EXPECT_FALSE(Thread::Current()->IsExceptionPending());
547 
548   // Get class for exception we expect to be thrown
549   ScopedLocalRef<jclass> jlre(env_, env_->FindClass("java/lang/RuntimeException"));
550   SetUpForTest(false, "throwException", "()V",
551                reinterpret_cast<void*>(&Java_MyClassNatives_throwException));
552   // Call Java_MyClassNatives_throwException (JNI method that throws exception)
553   env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
554   EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
555   EXPECT_TRUE(env_->ExceptionCheck() == JNI_TRUE);
556   ScopedLocalRef<jthrowable> exception(env_, env_->ExceptionOccurred());
557   env_->ExceptionClear();
558   EXPECT_TRUE(env_->IsInstanceOf(exception.get(), jlre.get()));
559 
560   // Check a single call of a JNI method is ok
561   SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
562   env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
563   EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
564 }
565 
Java_MyClassNatives_nativeUpCall(JNIEnv * env,jobject thisObj,jint i)566 jint Java_MyClassNatives_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
567   if (i <= 0) {
568     // We want to check raw Object*/Array* below
569     ScopedObjectAccess soa(env);
570 
571     // Build stack trace
572     jobject internal = Thread::Current()->CreateInternalStackTrace(soa);
573     jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal);
574     mirror::ObjectArray<mirror::StackTraceElement>* trace_array =
575         soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array);
576     EXPECT_TRUE(trace_array != NULL);
577     EXPECT_EQ(11, trace_array->GetLength());
578 
579     // Check stack trace entries have expected values
580     for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
581       EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
582       mirror::StackTraceElement* ste = trace_array->Get(i);
583       EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
584       EXPECT_STREQ("MyClassNatives", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
585       EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
586     }
587 
588     // end recursion
589     return 0;
590   } else {
591     jclass jklass = env->FindClass("MyClassNatives");
592     EXPECT_TRUE(jklass != NULL);
593     jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
594     EXPECT_TRUE(jmethod != NULL);
595 
596     // Recurse with i - 1
597     jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
598 
599     // Return sum of all depths
600     return i + result;
601   }
602 }
603 
TEST_F(JniCompilerTest,NativeStackTraceElement)604 TEST_F(JniCompilerTest, NativeStackTraceElement) {
605   TEST_DISABLED_FOR_PORTABLE();
606   SetUpForTest(false, "fooI", "(I)I",
607                reinterpret_cast<void*>(&Java_MyClassNatives_nativeUpCall));
608   jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
609   EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
610 }
611 
Java_MyClassNatives_fooO(JNIEnv * env,jobject,jobject x)612 jobject Java_MyClassNatives_fooO(JNIEnv* env, jobject, jobject x) {
613   return env->NewGlobalRef(x);
614 }
615 
TEST_F(JniCompilerTest,ReturnGlobalRef)616 TEST_F(JniCompilerTest, ReturnGlobalRef) {
617   TEST_DISABLED_FOR_PORTABLE();
618   SetUpForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
619                reinterpret_cast<void*>(&Java_MyClassNatives_fooO));
620   jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
621   EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
622   EXPECT_TRUE(env_->IsSameObject(result, jobj_));
623 }
624 
local_ref_test(JNIEnv * env,jobject thisObj,jint x)625 jint local_ref_test(JNIEnv* env, jobject thisObj, jint x) {
626   // Add 10 local references
627   ScopedObjectAccess soa(env);
628   for (int i = 0; i < 10; i++) {
629     soa.AddLocalReference<jobject>(soa.Decode<mirror::Object*>(thisObj));
630   }
631   return x+1;
632 }
633 
TEST_F(JniCompilerTest,LocalReferenceTableClearingTest)634 TEST_F(JniCompilerTest, LocalReferenceTableClearingTest) {
635   TEST_DISABLED_FOR_PORTABLE();
636   SetUpForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
637   // 1000 invocations of a method that adds 10 local references
638   for (int i = 0; i < 1000; i++) {
639     jint result = env_->CallIntMethod(jobj_, jmethod_, i);
640     EXPECT_TRUE(result == i + 1);
641   }
642 }
643 
my_arraycopy(JNIEnv * env,jclass klass,jobject src,jint src_pos,jobject dst,jint dst_pos,jint length)644 void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
645   EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
646   EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
647   EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
648   EXPECT_EQ(1234, src_pos);
649   EXPECT_EQ(5678, dst_pos);
650   EXPECT_EQ(9876, length);
651 }
652 
TEST_F(JniCompilerTest,JavaLangSystemArrayCopy)653 TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
654   TEST_DISABLED_FOR_PORTABLE();
655   SetUpForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
656                reinterpret_cast<void*>(&my_arraycopy));
657   env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
658 }
659 
my_casi(JNIEnv * env,jobject unsafe,jobject obj,jlong offset,jint expected,jint newval)660 jboolean my_casi(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jint expected, jint newval) {
661   EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, unsafe));
662   EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj));
663   EXPECT_EQ(0x12345678ABCDEF88ll, offset);
664   EXPECT_EQ(static_cast<jint>(0xCAFEF00D), expected);
665   EXPECT_EQ(static_cast<jint>(0xEBADF00D), newval);
666   return JNI_TRUE;
667 }
668 
TEST_F(JniCompilerTest,CompareAndSwapInt)669 TEST_F(JniCompilerTest, CompareAndSwapInt) {
670   TEST_DISABLED_FOR_PORTABLE();
671   SetUpForTest(false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
672                reinterpret_cast<void*>(&my_casi));
673   jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
674   EXPECT_EQ(result, JNI_TRUE);
675 }
676 
my_gettext(JNIEnv * env,jclass klass,jlong val1,jobject obj1,jlong val2,jobject obj2)677 jint my_gettext(JNIEnv* env, jclass klass, jlong val1, jobject obj1, jlong val2, jobject obj2) {
678   EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
679   EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj1));
680   EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj2));
681   EXPECT_EQ(0x12345678ABCDEF88ll, val1);
682   EXPECT_EQ(0x7FEDCBA987654321ll, val2);
683   return 42;
684 }
685 
TEST_F(JniCompilerTest,GetText)686 TEST_F(JniCompilerTest, GetText) {
687   TEST_DISABLED_FOR_PORTABLE();
688   SetUpForTest(true, "getText", "(JLjava/lang/Object;JLjava/lang/Object;)I",
689                reinterpret_cast<void*>(&my_gettext));
690   jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 0x12345678ABCDEF88ll, jobj_,
691                                           0x7FEDCBA987654321ll, jobj_);
692   EXPECT_EQ(result, 42);
693 }
694 
TEST_F(JniCompilerTest,GetSinkPropertiesNative)695 TEST_F(JniCompilerTest, GetSinkPropertiesNative) {
696   TEST_DISABLED_FOR_PORTABLE();
697   SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", NULL);
698   // This space intentionally left blank. Just testing compilation succeeds.
699 }
700 
701 // This should return jclass, but we're imitating a bug pattern.
Java_MyClassNatives_instanceMethodThatShouldReturnClass(JNIEnv * env,jobject)702 jobject Java_MyClassNatives_instanceMethodThatShouldReturnClass(JNIEnv* env, jobject) {
703   return env->NewStringUTF("not a class!");
704 }
705 
706 // This should return jclass, but we're imitating a bug pattern.
Java_MyClassNatives_staticMethodThatShouldReturnClass(JNIEnv * env,jclass)707 jobject Java_MyClassNatives_staticMethodThatShouldReturnClass(JNIEnv* env, jclass) {
708   return env->NewStringUTF("not a class!");
709 }
710 
TEST_F(JniCompilerTest,UpcallReturnTypeChecking_Instance)711 TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Instance) {
712   TEST_DISABLED_FOR_PORTABLE();
713   SetUpForTest(false, "instanceMethodThatShouldReturnClass", "()Ljava/lang/Class;",
714                reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldReturnClass));
715 
716   CheckJniAbortCatcher check_jni_abort_catcher;
717   // TODO: check type of returns with portable JNI compiler.
718   // This native method is bad, and tries to return a jstring as a jclass.
719   env_->CallObjectMethod(jobj_, jmethod_);
720   check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
721 
722   // Here, we just call the method incorrectly; we should catch that too.
723   env_->CallVoidMethod(jobj_, jmethod_);
724   check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
725   env_->CallStaticVoidMethod(jklass_, jmethod_);
726   check_jni_abort_catcher.Check("calling non-static method java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass() with CallStaticVoidMethodV");
727 }
728 
TEST_F(JniCompilerTest,UpcallReturnTypeChecking_Static)729 TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Static) {
730   TEST_DISABLED_FOR_PORTABLE();
731   SetUpForTest(true, "staticMethodThatShouldReturnClass", "()Ljava/lang/Class;",
732                reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldReturnClass));
733 
734   CheckJniAbortCatcher check_jni_abort_catcher;
735   // TODO: check type of returns with portable JNI compiler.
736   // This native method is bad, and tries to return a jstring as a jclass.
737   env_->CallStaticObjectMethod(jklass_, jmethod_);
738   check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass()");
739 
740   // Here, we just call the method incorrectly; we should catch that too.
741   env_->CallStaticVoidMethod(jklass_, jmethod_);
742   check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass()");
743   env_->CallVoidMethod(jobj_, jmethod_);
744   check_jni_abort_catcher.Check("calling static method java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass() with CallVoidMethodV");
745 }
746 
747 // This should take jclass, but we're imitating a bug pattern.
Java_MyClassNatives_instanceMethodThatShouldTakeClass(JNIEnv *,jobject,jclass)748 void Java_MyClassNatives_instanceMethodThatShouldTakeClass(JNIEnv*, jobject, jclass) {
749 }
750 
751 // This should take jclass, but we're imitating a bug pattern.
Java_MyClassNatives_staticMethodThatShouldTakeClass(JNIEnv *,jclass,jclass)752 void Java_MyClassNatives_staticMethodThatShouldTakeClass(JNIEnv*, jclass, jclass) {
753 }
754 
TEST_F(JniCompilerTest,UpcallArgumentTypeChecking_Instance)755 TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Instance) {
756   TEST_DISABLED_FOR_PORTABLE();
757   SetUpForTest(false, "instanceMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
758                reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldTakeClass));
759 
760   CheckJniAbortCatcher check_jni_abort_catcher;
761   // We deliberately pass a bad second argument here.
762   env_->CallVoidMethod(jobj_, jmethod_, 123, env_->NewStringUTF("not a class!"));
763   check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.instanceMethodThatShouldTakeClass(int, java.lang.Class)");
764 }
765 
TEST_F(JniCompilerTest,UpcallArgumentTypeChecking_Static)766 TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Static) {
767   TEST_DISABLED_FOR_PORTABLE();
768   SetUpForTest(true, "staticMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
769                reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldTakeClass));
770 
771   CheckJniAbortCatcher check_jni_abort_catcher;
772   // We deliberately pass a bad second argument here.
773   env_->CallStaticVoidMethod(jklass_, jmethod_, 123, env_->NewStringUTF("not a class!"));
774   check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.staticMethodThatShouldTakeClass(int, java.lang.Class)");
775 }
776 
777 }  // namespace art
778