Create JNIEnv*s on the right threads.

This exposes a bug in jni_compiler.cc --- it passes the right JNIEnv* to the
native method and to MonitorExit, but it passes a bogus value to MonitorEnter.

Change-Id: Icbf505d24294d14ce3e40180a20254789cb69904
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index 7677a7a..cfedb85 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -171,8 +171,9 @@
 }
 
 int gJava_MyClass_fooSIOO_calls = 0;
-jobject Java_MyClass_fooSIOO(JNIEnv*, jclass klass, jint x, jobject y,
+jobject Java_MyClass_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
                              jobject z) {
+  EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
   EXPECT_EQ(3u, Thread::Current()->NumShbHandles());
   EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
   gJava_MyClass_fooSIOO_calls++;
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index dbdfc45..f77e4d0 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -43,8 +43,9 @@
     Thread* env_self = reinterpret_cast<JNIEnvExt*>(env)->self;
     Thread* self = workAroundAppJniBugs ? Thread::Current() : env_self;
     if (self != env_self) {
-      LOG(ERROR) << "JNI ERROR: JNIEnv for thread " << env_self << " used on "
-          << "thread " << self << ")";
+      LOG(ERROR) << "JNI ERROR: JNIEnv for " << *env_self
+          << " used on " << *self;
+      // TODO: dump stack
     }
     return self;
   }
@@ -1757,17 +1758,21 @@
 };
 
 void MonitorEnterHelper(JNIEnv* env, jobject obj) {
+  CHECK_EQ(Thread::Current()->GetJniEnv(), env);
   MonitorEnter(env, obj);  // Ignore the result.
 }
 
 void MonitorExitHelper(JNIEnv* env, jobject obj) {
+  CHECK_EQ(Thread::Current()->GetJniEnv(), env);
   MonitorExit(env, obj);  // Ignore the result.
 }
 
 JNIEnv* CreateJNIEnv() {
+  Thread* self = Thread::Current();
+  CHECK(self != NULL);
   JNIEnvExt* result = (JNIEnvExt*) calloc(1, sizeof(JNIEnvExt));
   result->fns = &gNativeInterface;
-  result->self = Thread::Current();
+  result->self = self;
   result->MonitorEnterHelper = &MonitorEnterHelper;
   result->MonitorExitHelper = &MonitorExitHelper;
   return reinterpret_cast<JNIEnv*>(result);
diff --git a/src/thread.cc b/src/thread.cc
index 68f4566..b98d1e5 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -101,6 +101,8 @@
       PLOG(FATAL) << "pthread_setspecific failed";
   }
 
+  thread->jni_env_ = CreateJNIEnv();
+
   return thread;
 }
 
@@ -144,6 +146,14 @@
   return os;
 }
 
+std::ostream& operator<<(std::ostream& os, const Thread& thread) {
+  os << "Thread[" << &thread
+      << ",id=" << thread.GetId()
+      << ",tid=" << thread.GetNativeId()
+      << ",state=" << thread.GetState() << "]";
+  return os;
+}
+
 ThreadList* ThreadList::Create() {
   return new ThreadList;
 }
diff --git a/src/thread.h b/src/thread.h
index 02b2f65..a6e137f 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -171,7 +171,7 @@
     return runtime_;
   }
 
-  State GetState() {
+  State GetState() const {
     return state_;
   }
 
@@ -241,8 +241,11 @@
 
  private:
   Thread()
-      : id_(1234), top_shb_(NULL), exception_(NULL), suspend_count_(0) {
-    jni_env_ = CreateJNIEnv();
+      : id_(1234),
+        top_shb_(NULL),
+        jni_env_(NULL),
+        exception_(NULL),
+        suspend_count_(0) {
   }
 
   ~Thread() {
@@ -304,6 +307,7 @@
 
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
+std::ostream& operator<<(std::ostream& os, const Thread& thread);
 std::ostream& operator<<(std::ostream& os, const Thread::State& state);
 
 class ThreadList {