Add some missing JNI string functions, GetObjectArrayElement, and all the primitive array region functions.
This also pulls the UTF-8/UTF-16 functions out of class String.
Change-Id: I75936b84fd619c9cf91f6e6a6037488220b05781
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 0d46f29..79986c2 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -532,6 +532,35 @@
return AddLocalReference<JniT>(ts, result);
}
+void ThrowAIOOBE(ScopedJniThreadState& ts, Array* array, jsize start, jsize length, const char* identifier) {
+ std::string type(PrettyType(array));
+ ts.Self()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
+ "%s offset=%d length=%d %s.length=%d",
+ type.c_str(), start, length, identifier, array->GetLength());
+}
+
+template <typename JavaArrayT, typename JavaT, typename ArrayT>
+static void GetPrimitiveArrayRegion(ScopedJniThreadState& ts, JavaArrayT java_array, jsize start, jsize length, JavaT* buf) {
+ ArrayT* array = Decode<ArrayT*>(ts, java_array);
+ if (start < 0 || length < 0 || start + length > array->GetLength()) {
+ ThrowAIOOBE(ts, array, start, length, "src");
+ } else {
+ JavaT* data = array->GetData();
+ memcpy(buf, data + start, length * sizeof(JavaT));
+ }
+}
+
+template <typename JavaArrayT, typename JavaT, typename ArrayT>
+static void SetPrimitiveArrayRegion(ScopedJniThreadState& ts, JavaArrayT java_array, jsize start, jsize length, const JavaT* buf) {
+ ArrayT* array = Decode<ArrayT*>(ts, java_array);
+ if (start < 0 || length < 0 || start + length > array->GetLength()) {
+ ThrowAIOOBE(ts, array, start, length, "dst");
+ } else {
+ JavaT* data = array->GetData();
+ memcpy(data + start, buf, length * sizeof(JavaT));
+ }
+}
+
} // namespace
class JNI {
@@ -1667,27 +1696,13 @@
InvokeWithJValues(ts, NULL, methodID, args);
}
- static jstring NewString(JNIEnv* env, const jchar* unicode, jsize len) {
+ static jstring NewString(JNIEnv* env, const jchar* chars, jsize char_count) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
- }
-
- static jsize GetStringLength(JNIEnv* env, jstring str) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return 0;
- }
-
- static const jchar* GetStringChars(JNIEnv* env, jstring str, jboolean* isCopy) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
- }
-
- static void ReleaseStringChars(JNIEnv* env, jstring str, const jchar* chars) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ if (chars == NULL && char_count == 0) {
+ return NULL;
+ }
+ String* result = String::AllocFromUtf16(char_count, chars);
+ return AddLocalReference<jstring>(ts, result);
}
static jstring NewStringUTF(JNIEnv* env, const char* utf) {
@@ -1699,10 +1714,35 @@
return AddLocalReference<jstring>(ts, result);
}
- static jsize GetStringUTFLength(JNIEnv* env, jstring str) {
+ static jsize GetStringLength(JNIEnv* env, jstring java_string) {
+ ScopedJniThreadState ts(env);
+ return Decode<String*>(ts, java_string)->GetLength();
+ }
+
+ static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) {
+ ScopedJniThreadState ts(env);
+ return Decode<String*>(ts, java_string)->GetUtfLength();
+ }
+
+ static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
ScopedJniThreadState ts(env);
UNIMPLEMENTED(FATAL);
- return 0;
+ }
+
+ static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
+ ScopedJniThreadState ts(env);
+ UNIMPLEMENTED(FATAL);
+ }
+
+ static const jchar* GetStringChars(JNIEnv* env, jstring str, jboolean* isCopy) {
+ ScopedJniThreadState ts(env);
+ UNIMPLEMENTED(FATAL);
+ return NULL;
+ }
+
+ static void ReleaseStringChars(JNIEnv* env, jstring str, const jchar* chars) {
+ ScopedJniThreadState ts(env);
+ UNIMPLEMENTED(FATAL);
}
static const char* GetStringUTFChars(JNIEnv* env, jstring str, jboolean* isCopy) {
@@ -1724,10 +1764,10 @@
return array->GetLength();
}
- static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
+ static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- return NULL;
+ ObjectArray<Object>* array = Decode<ObjectArray<Object>*>(ts, java_array);
+ return AddLocalReference<jobject>(ts, array->Get(index));
}
static void SetObjectArrayElement(JNIEnv* env,
@@ -1901,100 +1941,84 @@
UNIMPLEMENTED(FATAL);
}
- static void GetBooleanArrayRegion(JNIEnv* env,
- jbooleanArray array, jsize start, jsize l, jboolean* buf) {
+ static void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, jboolean* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ GetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(ts, array, start, length, buf);
}
- static void GetByteArrayRegion(JNIEnv* env,
- jbyteArray array, jsize start, jsize len, jbyte* buf) {
+ static void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, jbyte* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ GetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(ts, array, start, length, buf);
}
- static void GetCharArrayRegion(JNIEnv* env,
- jcharArray array, jsize start, jsize len, jchar* buf) {
+ static void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, jchar* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ GetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(ts, array, start, length, buf);
}
- static void GetShortArrayRegion(JNIEnv* env,
- jshortArray array, jsize start, jsize len, jshort* buf) {
+ static void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, jdouble* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ GetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(ts, array, start, length, buf);
}
- static void GetIntArrayRegion(JNIEnv* env,
- jintArray array, jsize start, jsize len, jint* buf) {
+ static void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, jfloat* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ GetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(ts, array, start, length, buf);
}
- static void GetLongArrayRegion(JNIEnv* env,
- jlongArray array, jsize start, jsize len, jlong* buf) {
+ static void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, jint* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ GetPrimitiveArrayRegion<jintArray, jint, IntArray>(ts, array, start, length, buf);
}
- static void GetFloatArrayRegion(JNIEnv* env,
- jfloatArray array, jsize start, jsize len, jfloat* buf) {
+ static void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, jlong* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ GetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(ts, array, start, length, buf);
}
- static void GetDoubleArrayRegion(JNIEnv* env,
- jdoubleArray array, jsize start, jsize len, jdouble* buf) {
+ static void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, jshort* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ GetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(ts, array, start, length, buf);
}
- static void SetBooleanArrayRegion(JNIEnv* env,
- jbooleanArray array, jsize start, jsize l, const jboolean* buf) {
+ static void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, const jboolean* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ SetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(ts, array, start, length, buf);
}
- static void SetByteArrayRegion(JNIEnv* env,
- jbyteArray array, jsize start, jsize len, const jbyte* buf) {
+ static void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, const jbyte* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ SetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(ts, array, start, length, buf);
}
- static void SetCharArrayRegion(JNIEnv* env,
- jcharArray array, jsize start, jsize len, const jchar* buf) {
+ static void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, const jchar* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ SetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(ts, array, start, length, buf);
}
- static void SetShortArrayRegion(JNIEnv* env,
- jshortArray array, jsize start, jsize len, const jshort* buf) {
+ static void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, const jdouble* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ SetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(ts, array, start, length, buf);
}
- static void SetIntArrayRegion(JNIEnv* env,
- jintArray array, jsize start, jsize len, const jint* buf) {
+ static void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, const jfloat* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ SetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(ts, array, start, length, buf);
}
- static void SetLongArrayRegion(JNIEnv* env,
- jlongArray array, jsize start, jsize len, const jlong* buf) {
+ static void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, const jint* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ SetPrimitiveArrayRegion<jintArray, jint, IntArray>(ts, array, start, length, buf);
}
- static void SetFloatArrayRegion(JNIEnv* env,
- jfloatArray array, jsize start, jsize len, const jfloat* buf) {
+ static void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, const jlong* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ SetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(ts, array, start, length, buf);
}
- static void SetDoubleArrayRegion(JNIEnv* env,
- jdoubleArray array, jsize start, jsize len, const jdouble* buf) {
+ static void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, const jshort* buf) {
ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
+ SetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(ts, array, start, length, buf);
}
static jint RegisterNatives(JNIEnv* env,
@@ -2063,18 +2087,6 @@
return (*vm != NULL) ? JNI_OK : JNI_ERR;
}
- static void GetStringRegion(JNIEnv* env,
- jstring str, jsize start, jsize len, jchar* buf) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
- static void GetStringUTFRegion(JNIEnv* env,
- jstring str, jsize start, jsize len, char* buf) {
- ScopedJniThreadState ts(env);
- UNIMPLEMENTED(FATAL);
- }
-
static void* GetPrimitiveArrayCritical(JNIEnv* env,
jarray array, jboolean* isCopy) {
ScopedJniThreadState ts(env);
@@ -2549,7 +2561,7 @@
* human-readable description of the error or NULL if no detail is
* available; ownership of the string is transferred to the caller.
*/
-bool JavaVMExt::LoadNativeLibrary(const std::string& path, Object* class_loader, char** detail) {
+bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_loader, char** detail) {
*detail = NULL;
// See if we've already loaded this library. If we have, and the class loader
@@ -2644,11 +2656,10 @@
// loader, which will always be "null" since the stuff at the
// top of the stack is around Runtime.loadLibrary(). (See
// the comments in the JNI FindClass function.)
- UNIMPLEMENTED(WARNING) << "need to override current class loader";
typedef int (*JNI_OnLoadFn)(JavaVM*, void*);
JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
- //Object* prevOverride = self->classLoaderOverride;
- //self->classLoaderOverride = classLoader;
+ ClassLoader* old_class_loader = self->GetClassLoaderOverride();
+ self->SetClassLoaderOverride(class_loader);
old_state = self->GetState();
self->SetState(Thread::kNative);
@@ -2658,8 +2669,7 @@
int version = (*jni_on_load)(reinterpret_cast<JavaVM*>(this), NULL);
self->SetState(old_state);
- UNIMPLEMENTED(WARNING) << "need to restore current class loader";
- //self->classLoaderOverride = prevOverride;
+ self->SetClassLoaderOverride(old_class_loader);;
if (version != JNI_VERSION_1_2 &&
version != JNI_VERSION_1_4 &&