Implement field access (and a few other bits and bobs).
Change-Id: I837eb0ae4af8e314761bb42d3405f05b7a79573e
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 4fb433f..7d5a447 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -14,8 +14,12 @@
protected:
void AssertNonExistentClass(const StringPiece& descriptor) {
EXPECT_TRUE(class_linker_->FindSystemClass(descriptor) == NULL);
- EXPECT_TRUE(Thread::Current()->IsExceptionPending());
- Thread::Current()->ClearException();
+ Thread* self = Thread::Current();
+ EXPECT_TRUE(self->IsExceptionPending());
+ Object* exception = self->GetException();
+ self->ClearException();
+ Class* exception_class = class_linker_->FindSystemClass("Ljava/lang/NoClassDefFoundError;");
+ EXPECT_TRUE(exception->InstanceOf(exception_class));
}
void AssertPrimitiveClass(const StringPiece& descriptor) {
diff --git a/src/common_test.h b/src/common_test.h
index d562226..a405ce5 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -197,6 +197,49 @@
"ABwBAAAFAAAAAwAAAGwBAAAGAAAAAQAAAIQBAAABIAAAAgAAAKQBAAACIAAAHAAAADwCAAADIAAA"
"AgAAAOICAAAAIAAAAQAAAPUCAAAAEAAAAQAAABwDAAA=";
+// class AllFields {
+// static boolean sZ;
+// static byte sB;
+// static char sC;
+// static double sD;
+// static float sF;
+// static int sI;
+// static long sJ;
+// static short sS;
+// static Object sObject;
+// static Object[] sObjectArray;
+//
+// boolean iZ;
+// byte iB;
+// char iC;
+// double iD;
+// float iF;
+// int iI;
+// long iJ;
+// short iS;
+// Object iObject;
+// Object[] iObjectArray;
+// }
+static const char kAllFields[] =
+ "ZGV4CjAzNQCdaMDlt1s2Pw65nbVCJcCcZcmroYXvMF/AAwAAcAAAAHhWNBIAAAAAAAAAACwDAAAi"
+ "AAAAcAAAAAwAAAD4AAAAAQAAACgBAAAUAAAANAEAAAIAAADUAQAAAQAAAOQBAAC8AQAABAIAABwC"
+ "AAAkAgAANAIAADcCAAA6AgAAPQIAAEACAABDAgAARgIAAFMCAABnAgAAagIAAG0CAABwAgAAhQIA"
+ "AIkCAACNAgAAkQIAAJUCAACZAgAAnQIAAKYCAAC0AgAAuAIAALwCAADAAgAAxAIAAMgCAADMAgAA"
+ "0AIAANQCAADdAgAA6wIAAO8CAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAoAAAAL"
+ "AAAADAAAAA0AAAALAAAACQAAAAAAAAAGAAAADgAAAAYAAQAPAAAABgACABAAAAAGAAMAEQAAAAYA"
+ "BAASAAAABgAFABMAAAAGAAcAFAAAAAYACwAVAAAABgAIABYAAAAGAAoAFwAAAAYAAAAYAAAABgAB"
+ "ABkAAAAGAAIAGgAAAAYAAwAbAAAABgAEABwAAAAGAAUAHQAAAAYABwAeAAAABgALAB8AAAAGAAgA"
+ "IAAAAAYACgAhAAAABgAAAAAAAAAHAAAAAAAAAAYAAAAAAAAABwAAAAAAAAABAAAAAAAAAPgCAAAA"
+ "AAAAAQABAAEAAADzAgAABAAAAHAQAQAAAA4ABjxpbml0PgAOQWxsRmllbGRzLmphdmEAAUIAAUMA"
+ "AUQAAUYAAUkAAUoAC0xBbGxGaWVsZHM7ABJMamF2YS9sYW5nL09iamVjdDsAAVMAAVYAAVoAE1tM"
+ "amF2YS9sYW5nL09iamVjdDsAAmlCAAJpQwACaUQAAmlGAAJpSQACaUoAB2lPYmplY3QADGlPYmpl"
+ "Y3RBcnJheQACaVMAAmlaAAJzQgACc0MAAnNEAAJzRgACc0kAAnNKAAdzT2JqZWN0AAxzT2JqZWN0"
+ "QXJyYXkAAnNTAAJzWgADAAcOAAoKAQAKCAEIAQgBCAEIAQgBCAEIAQgBCAAAAQABAAEAAQABAAEA"
+ "AQABAAEAAICABIQEAAAMAAAAAAAAAAEAAAAAAAAAAQAAACIAAABwAAAAAgAAAAwAAAD4AAAAAwAA"
+ "AAEAAAAoAQAABAAAABQAAAA0AQAABQAAAAIAAADUAQAABgAAAAEAAADkAQAAASAAAAEAAAAEAgAA"
+ "AiAAACIAAAAcAgAAAyAAAAEAAADzAgAAACAAAAEAAAD4AgAAABAAAAEAAAAsAwAA";
+
+
// class Main {
// public static void main(String args[]) {
// }
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index a892a28..243a29d 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -582,10 +582,10 @@
return AddLocalReference<jobject>(ts, field);
}
- static jclass GetSuperclass(JNIEnv* env, jclass sub) {
+ static jclass GetSuperclass(JNIEnv* env, jclass java_class) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ Class* c = Decode<Class*>(ts, java_class);
+ return AddLocalReference<jclass>(ts, c->GetSuperClass());
}
static jboolean IsAssignableFrom(JNIEnv* env, jclass sub, jclass sup) {
@@ -749,10 +749,13 @@
return 0;
}
- static jobject AllocObject(JNIEnv* env, jclass clazz) {
+ static jobject AllocObject(JNIEnv* env, jclass java_class) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ Class* c = Decode<Class*>(ts, java_class);
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
+ return NULL;
+ }
+ return AddLocalReference<jobject>(ts, c->NewInstance());
}
static jobject NewObject(JNIEnv* env, jclass clazz, jmethodID methodID, ...) {
@@ -764,23 +767,27 @@
return result;
}
- static jobject NewObjectV(JNIEnv* env,
- jclass clazz, jmethodID methodID, va_list args) {
+ static jobject NewObjectV(JNIEnv* env, jclass java_class, jmethodID methodID, va_list args) {
ScopedJniThreadState ts(env);
- Class* klass = Decode<Class*>(ts, clazz);
- Object* result = klass->NewInstance();
+ Class* c = Decode<Class*>(ts, java_class);
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
+ return NULL;
+ }
+ Object* result = c->NewInstance();
jobject local_result = AddLocalReference<jobject>(ts, result);
- CallNonvirtualVoidMethodV(env, local_result, clazz, methodID, args);
+ CallNonvirtualVoidMethodV(env, local_result, java_class, methodID, args);
return local_result;
}
- static jobject NewObjectA(JNIEnv* env,
- jclass clazz, jmethodID methodID, jvalue* args) {
+ static jobject NewObjectA(JNIEnv* env, jclass java_class, jmethodID methodID, jvalue* args) {
ScopedJniThreadState ts(env);
- Class* klass = Decode<Class*>(ts, clazz);
- Object* result = klass->NewInstance();
+ Class* c = Decode<Class*>(ts, java_class);
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c)) {
+ return NULL;
+ }
+ Object* result = c->NewInstance();
jobject local_result = AddLocalReference<jobjectArray>(ts, result);
- CallNonvirtualVoidMethodA(env, local_result, clazz, methodID, args);
+ CallNonvirtualVoidMethodA(env, local_result, java_class, methodID, args);
return local_result;
}
@@ -1245,103 +1252,172 @@
return FindFieldID(ts, c, name, sig, true);
}
- static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fieldID) {
+ static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fid) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ Object* o = Decode<Object*>(ts, obj);
+ Field* f = DecodeField(ts, fid);
+ return AddLocalReference<jobject>(ts, f->GetObject(o));
}
- static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fieldID) {
+ static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return JNI_FALSE;
+ Field* f = DecodeField(ts, fid);
+ return AddLocalReference<jobject>(ts, f->GetObject(NULL));
}
- static jbyte GetByteField(JNIEnv* env, jobject obj, jfieldID fieldID) {
+ static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ Object* o = Decode<Object*>(ts, java_object);
+ Object* v = Decode<Object*>(ts, java_value);
+ Field* f = DecodeField(ts, fid);
+ f->SetObject(o, v);
}
- static jchar GetCharField(JNIEnv* env, jobject obj, jfieldID fieldID) {
+ static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ Object* v = Decode<Object*>(ts, java_value);
+ Field* f = DecodeField(ts, fid);
+ f->SetObject(NULL, v);
}
- static jshort GetShortField(JNIEnv* env, jobject obj, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+#define GET_PRIMITIVE_FIELD(fn, instance) \
+ ScopedJniThreadState ts(env); \
+ Object* o = Decode<Object*>(ts, instance); \
+ Field* f = DecodeField(ts, fid); \
+ return f->fn(o)
+
+#define SET_PRIMITIVE_FIELD(fn, instance, value) \
+ ScopedJniThreadState ts(env); \
+ Object* o = Decode<Object*>(ts, instance); \
+ Field* f = DecodeField(ts, fid); \
+ f->fn(o, value)
+
+ static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetBoolean, obj);
}
- static jint GetIntField(JNIEnv* env, jobject obj, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ static jbyte GetByteField(JNIEnv* env, jobject obj, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetByte, obj);
}
- static jlong GetLongField(JNIEnv* env, jobject obj, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ static jchar GetCharField(JNIEnv* env, jobject obj, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetChar, obj);
}
- static jfloat GetFloatField(JNIEnv* env, jobject obj, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ static jshort GetShortField(JNIEnv* env, jobject obj, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetShort, obj);
}
- static jdouble GetDoubleField(JNIEnv* env, jobject obj, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
+ static jint GetIntField(JNIEnv* env, jobject obj, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetInt, obj);
}
- static void SetObjectField(JNIEnv* env, jobject obj, jfieldID fieldID, jobject val) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ static jlong GetLongField(JNIEnv* env, jobject obj, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetLong, obj);
}
- static void SetBooleanField(JNIEnv* env, jobject obj, jfieldID fieldID, jboolean val) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ static jfloat GetFloatField(JNIEnv* env, jobject obj, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetFloat, obj);
}
- static void SetByteField(JNIEnv* env, jobject obj, jfieldID fieldID, jbyte val) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ static jdouble GetDoubleField(JNIEnv* env, jobject obj, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetDouble, obj);
}
- static void SetCharField(JNIEnv* env, jobject obj, jfieldID fieldID, jchar val) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ static jboolean GetStaticBooleanField(JNIEnv* env, jclass clazz, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetBoolean, NULL);
}
- static void SetShortField(JNIEnv* env, jobject obj, jfieldID fieldID, jshort val) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ static jbyte GetStaticByteField(JNIEnv* env, jclass clazz, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetByte, NULL);
}
- static void SetIntField(JNIEnv* env, jobject obj, jfieldID fieldID, jint val) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ static jchar GetStaticCharField(JNIEnv* env, jclass clazz, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetChar, NULL);
}
- static void SetLongField(JNIEnv* env, jobject obj, jfieldID fieldID, jlong val) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ static jshort GetStaticShortField(JNIEnv* env, jclass clazz, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetShort, NULL);
}
- static void SetFloatField(JNIEnv* env, jobject obj, jfieldID fieldID, jfloat val) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ static jint GetStaticIntField(JNIEnv* env, jclass clazz, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetInt, NULL);
}
- static void SetDoubleField(JNIEnv* env, jobject obj, jfieldID fieldID, jdouble val) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ static jlong GetStaticLongField(JNIEnv* env, jclass clazz, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetLong, NULL);
+ }
+
+ static jfloat GetStaticFloatField(JNIEnv* env, jclass clazz, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetFloat, NULL);
+ }
+
+ static jdouble GetStaticDoubleField(JNIEnv* env, jclass clazz, jfieldID fid) {
+ GET_PRIMITIVE_FIELD(GetDouble, NULL);
+ }
+
+ static void SetBooleanField(JNIEnv* env, jobject obj, jfieldID fid, jboolean v) {
+ SET_PRIMITIVE_FIELD(SetBoolean, obj, v);
+ }
+
+ static void SetByteField(JNIEnv* env, jobject obj, jfieldID fid, jbyte v) {
+ SET_PRIMITIVE_FIELD(SetByte, obj, v);
+ }
+
+ static void SetCharField(JNIEnv* env, jobject obj, jfieldID fid, jchar v) {
+ SET_PRIMITIVE_FIELD(SetChar, obj, v);
+ }
+
+ static void SetFloatField(JNIEnv* env, jobject obj, jfieldID fid, jfloat v) {
+ SET_PRIMITIVE_FIELD(SetFloat, obj, v);
+ }
+
+ static void SetDoubleField(JNIEnv* env, jobject obj, jfieldID fid, jdouble v) {
+ SET_PRIMITIVE_FIELD(SetDouble, obj, v);
+ }
+
+ static void SetIntField(JNIEnv* env, jobject obj, jfieldID fid, jint v) {
+ SET_PRIMITIVE_FIELD(SetInt, obj, v);
+ }
+
+ static void SetLongField(JNIEnv* env, jobject obj, jfieldID fid, jlong v) {
+ SET_PRIMITIVE_FIELD(SetLong, obj, v);
+ }
+
+ static void SetShortField(JNIEnv* env, jobject obj, jfieldID fid, jshort v) {
+ SET_PRIMITIVE_FIELD(SetShort, obj, v);
+ }
+
+ static void SetStaticBooleanField(JNIEnv* env, jclass, jfieldID fid, jboolean v) {
+ SET_PRIMITIVE_FIELD(SetBoolean, NULL, v);
+ }
+
+ static void SetStaticByteField(JNIEnv* env, jclass, jfieldID fid, jbyte v) {
+ SET_PRIMITIVE_FIELD(SetByte, NULL, v);
+ }
+
+ static void SetStaticCharField(JNIEnv* env, jclass, jfieldID fid, jchar v) {
+ SET_PRIMITIVE_FIELD(SetChar, NULL, v);
+ }
+
+ static void SetStaticFloatField(JNIEnv* env, jclass, jfieldID fid, jfloat v) {
+ SET_PRIMITIVE_FIELD(SetFloat, NULL, v);
+ }
+
+ static void SetStaticDoubleField(JNIEnv* env, jclass, jfieldID fid, jdouble v) {
+ SET_PRIMITIVE_FIELD(SetDouble, NULL, v);
+ }
+
+ static void SetStaticIntField(JNIEnv* env, jclass, jfieldID fid, jint v) {
+ SET_PRIMITIVE_FIELD(SetInt, NULL, v);
+ }
+
+ static void SetStaticLongField(JNIEnv* env, jclass, jfieldID fid, jlong v) {
+ SET_PRIMITIVE_FIELD(SetLong, NULL, v);
+ }
+
+ static void SetStaticShortField(JNIEnv* env, jclass, jfieldID fid, jshort v) {
+ SET_PRIMITIVE_FIELD(SetShort, NULL, v);
}
static jobject CallStaticObjectMethod(JNIEnv* env,
@@ -1558,114 +1634,6 @@
InvokeWithJValues(ts, NULL, methodID, args);
}
- static jobject GetStaticObjectField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
- }
-
- static jboolean GetStaticBooleanField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return JNI_FALSE;
- }
-
- static jbyte GetStaticByteField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
- }
-
- static jchar GetStaticCharField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
- }
-
- static jshort GetStaticShortField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
- }
-
- static jint GetStaticIntField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
- }
-
- static jlong GetStaticLongField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
- }
-
- static jfloat GetStaticFloatField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
- }
-
- static jdouble GetStaticDoubleField(JNIEnv* env, jclass clazz, jfieldID fieldID) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
- }
-
- static void SetStaticObjectField(JNIEnv* env,
- jclass clazz, jfieldID fieldID, jobject value) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
- static void SetStaticBooleanField(JNIEnv* env,
- jclass clazz, jfieldID fieldID, jboolean value) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
- static void SetStaticByteField(JNIEnv* env,
- jclass clazz, jfieldID fieldID, jbyte value) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
- static void SetStaticCharField(JNIEnv* env,
- jclass clazz, jfieldID fieldID, jchar value) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
- static void SetStaticShortField(JNIEnv* env,
- jclass clazz, jfieldID fieldID, jshort value) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
- static void SetStaticIntField(JNIEnv* env,
- jclass clazz, jfieldID fieldID, jint value) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
- static void SetStaticLongField(JNIEnv* env,
- jclass clazz, jfieldID fieldID, jlong value) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
- static void SetStaticFloatField(JNIEnv* env,
- jclass clazz, jfieldID fieldID, jfloat value) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
- static void SetStaticDoubleField(JNIEnv* env,
- jclass clazz, jfieldID fieldID, jdouble value) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
static jstring NewString(JNIEnv* env, const jchar* unicode, jsize len) {
ScopedJniThreadState ts(env);
UNIMPLEMENTED(FATAL);
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index 9043bcd..62f6068 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -19,6 +19,21 @@
JNIEnv* env_;
};
+TEST_F(JniInternalTest, AllocObject) {
+ jclass c = env_->FindClass("java/lang/String");
+ ASSERT_TRUE(c != NULL);
+ jobject o = env_->AllocObject(c);
+ ASSERT_TRUE(o != NULL);
+
+ // We have an instance of the class we asked for...
+ ASSERT_TRUE(env_->IsInstanceOf(o, c));
+ // ...whose fields haven't been initialized because
+ // we didn't call a constructor.
+ ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
+ ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I")));
+ ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == NULL);
+}
+
TEST_F(JniInternalTest, GetVersion) {
ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
}
@@ -303,6 +318,15 @@
// Already tested in NewObjectArray/NewPrimitiveArray.
}
+TEST_F(JniInternalTest, GetSuperclass) {
+ jclass object_class = env_->FindClass("java/lang/Object");
+ ASSERT_TRUE(object_class != NULL);
+ jclass string_class = env_->FindClass("java/lang/String");
+ ASSERT_TRUE(string_class != NULL);
+ ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
+ ASSERT_TRUE(env_->GetSuperclass(object_class) == NULL);
+}
+
TEST_F(JniInternalTest, NewStringUTF) {
EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
EXPECT_TRUE(env_->NewStringUTF("") != NULL);
@@ -331,6 +355,87 @@
// TODO: check ArrayStoreException thrown for bad types.
}
+#define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
+ do { \
+ jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
+ EXPECT_TRUE(fid != NULL); \
+ env_->SetStatic ## type ## Field(c, fid, value1); \
+ EXPECT_EQ(value1, env_->GetStatic ## type ## Field(c, fid)); \
+ env_->SetStatic ## type ## Field(c, fid, value2); \
+ EXPECT_EQ(value2, env_->GetStatic ## type ## Field(c, fid)); \
+ } while (false)
+
+#define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
+ do { \
+ jfieldID fid = env_->GetFieldID(c, field_name, sig); \
+ EXPECT_TRUE(fid != NULL); \
+ env_->Set ## type ## Field(instance, fid, value1); \
+ EXPECT_EQ(value1, env_->Get ## type ## Field(instance, fid)); \
+ env_->Set ## type ## Field(instance, fid, value2); \
+ EXPECT_EQ(value2, env_->Get ## type ## Field(instance, fid)); \
+ } while (false)
+
+
+TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
+ scoped_ptr<DexFile> dex(OpenDexFileBase64(kAllFields, "kAllFields"));
+ PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+ Thread::Current()->SetClassLoaderOverride(class_loader);
+
+ jclass c = env_->FindClass("AllFields");
+ ASSERT_TRUE(c != NULL);
+ jobject o = env_->AllocObject(c);
+ ASSERT_TRUE(o != NULL);
+
+ EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", true, false);
+ EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
+ EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
+ EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
+ EXPECT_STATIC_PRIMITIVE_FIELD(Float, "sF", "F", 1.0, 2.0);
+ EXPECT_STATIC_PRIMITIVE_FIELD(Int, "sI", "I", 1, 2);
+ EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
+ EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
+
+ EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", true, false);
+ EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
+ EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
+ EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
+ EXPECT_PRIMITIVE_FIELD(o, Float, "iF", "F", 1.0, 2.0);
+ EXPECT_PRIMITIVE_FIELD(o, Int, "iI", "I", 1, 2);
+ EXPECT_PRIMITIVE_FIELD(o, Long, "iJ", "J", 1, 2);
+ EXPECT_PRIMITIVE_FIELD(o, Short, "iS", "S", 1, 2);
+}
+
+TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
+ scoped_ptr<DexFile> dex(OpenDexFileBase64(kAllFields, "kAllFields"));
+ PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+ Thread::Current()->SetClassLoaderOverride(class_loader);
+
+ jclass c = env_->FindClass("AllFields");
+ ASSERT_TRUE(c != NULL);
+ jobject o = env_->AllocObject(c);
+ ASSERT_TRUE(o != NULL);
+
+ jstring s1 = env_->NewStringUTF("hello");
+ ASSERT_TRUE(s1 != NULL);
+ jstring s2 = env_->NewStringUTF("world");
+ ASSERT_TRUE(s2 != NULL);
+
+ jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;");
+ ASSERT_TRUE(s_fid != NULL);
+ jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;");
+ ASSERT_TRUE(i_fid != NULL);
+
+ env_->SetStaticObjectField(c, s_fid, s1);
+ ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid)));
+ env_->SetStaticObjectField(c, s_fid, s2);
+ ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid)));
+
+ env_->SetObjectField(o, i_fid, s1);
+ ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid)));
+ env_->SetObjectField(o, i_fid, s2);
+ ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
+}
+
TEST_F(JniInternalTest, NewLocalRef_NULL) {
EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
}
diff --git a/src/object.cc b/src/object.cc
index 9316660..6a349ac 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -226,7 +226,6 @@
void Field::SetByte(Object* object, int8_t b) const {
CHECK_EQ(GetType(), 'B');
- CHECK(IsStatic());
Set32(object, b);
}
@@ -237,7 +236,6 @@
void Field::SetChar(Object* object, uint16_t c) const {
CHECK_EQ(GetType(), 'C');
- CHECK(IsStatic());
Set32(object, c);
}
@@ -248,7 +246,6 @@
void Field::SetShort(Object* object, uint16_t s) const {
CHECK_EQ(GetType(), 'S');
- CHECK(IsStatic());
Set32(object, s);
}
@@ -259,7 +256,6 @@
void Field::SetInt(Object* object, int32_t i) const {
CHECK_EQ(GetType(), 'I');
- CHECK(IsStatic());
Set32(object, i);
}
@@ -270,7 +266,6 @@
void Field::SetLong(Object* object, int64_t j) const {
CHECK_EQ(GetType(), 'J');
- CHECK(IsStatic());
Set64(object, j);
}
@@ -283,7 +278,6 @@
void Field::SetFloat(Object* object, float f) const {
CHECK_EQ(GetType(), 'F');
- CHECK(IsStatic());
JValue float_bits;
float_bits.f = f;
Set32(object, float_bits.i);
@@ -298,7 +292,6 @@
void Field::SetDouble(Object* object, double d) const {
CHECK_EQ(GetType(), 'D');
- CHECK(IsStatic());
JValue double_bits;
double_bits.d = d;
Set64(object, double_bits.j);