Implement java.lang.reflect.Constructor.constructNative.
Change-Id: Iefa92ad1bd89073d4bfa9a80b9e4f0dea90a5849
diff --git a/build/Android.common.mk b/build/Android.common.mk
index b921281..ce04683 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -111,6 +111,7 @@
src/java_lang_Throwable.cc \
src/java_lang_VMClassLoader.cc \
src/java_lang_reflect_Array.cc \
+ src/java_lang_reflect_Constructor.cc \
src/java_lang_reflect_Field.cc \
src/java_lang_reflect_Method.cc \
src/java_util_concurrent_atomic_AtomicLong.cc \
diff --git a/src/class_linker.cc b/src/class_linker.cc
index fb47c48..769a336 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -453,6 +453,17 @@
init_done_ = true;
}
+void ClassLinker::RunRootClinits() {
+ Thread* self = Thread::Current();
+ for (size_t i = 0; i < ClassLinker::kClassRootsMax; ++i) {
+ Class* c = GetClassRoot(ClassRoot(i));
+ if (!c->IsArrayClass() && !c->IsPrimitive()) {
+ EnsureInitialized(GetClassRoot(ClassRoot(i)), true);
+ CHECK(!self->IsExceptionPending());
+ }
+ }
+}
+
struct ClassLinker::InitFromImageCallbackState {
ClassLinker* class_linker;
diff --git a/src/class_linker.h b/src/class_linker.h
index 09736ce..317490a 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -157,6 +157,10 @@
// given the restriction that no <clinit> execution is possible.
bool EnsureInitialized(Class* c, bool can_run_clinit);
+ // Initializes classes that have instances in the image but that have
+ // <clinit> methods so they could not be initialized by the compiler.
+ void RunRootClinits();
+
void RegisterDexFile(const DexFile& dex_file);
void RegisterDexFile(const DexFile& dex_file, DexCache* dex_cache);
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index d77e3f0..7d1a4aa 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -368,6 +368,10 @@
return NULL;
}
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
+ return NULL;
+ }
+
Method* init = c->FindDirectMethod("<init>", "()V");
if (init == NULL) {
Thread::Current()->ThrowNewException("Ljava/lang/InstantiationException;",
diff --git a/src/java_lang_reflect_Constructor.cc b/src/java_lang_reflect_Constructor.cc
new file mode 100644
index 0000000..10a8f07
--- /dev/null
+++ b/src/java_lang_reflect_Constructor.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni_internal.h"
+#include "class_linker.h"
+#include "object.h"
+#include "reflection.h"
+
+#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
+
+namespace art {
+
+namespace {
+
+/*
+ * We get here through Constructor.newInstance(). The Constructor object
+ * would not be available if the constructor weren't public (per the
+ * definition of Class.getConstructor), so we can skip the method access
+ * check. We can also safely assume the constructor isn't associated
+ * with an interface, array, or primitive class.
+ */
+jobject Constructor_constructNative(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs, jclass javaDeclaringClass, jobjectArray javaParams, jint, jboolean) {
+ Class* c = Decode<Class*>(env, javaDeclaringClass);
+ if (c->IsAbstract()) {
+ Thread::Current()->ThrowNewException("Ljava/lang/InstantiationException;",
+ "Can't instantiate abstract class %s", PrettyDescriptor(c->GetDescriptor()).c_str());
+ return NULL;
+ }
+
+ Object* receiver = c->AllocObject();
+ if (receiver == NULL) {
+ return NULL;
+ }
+
+ jobject javaReceiver = AddLocalReference<jobject>(env, receiver);
+ InvokeMethod(env, javaMethod, javaReceiver, javaArgs, javaParams);
+
+ // Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod.
+ return javaReceiver;
+}
+
+static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(Constructor, constructNative, "([Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Class;IZ)Ljava/lang/Object;"),
+};
+
+} // namespace
+
+void register_java_lang_reflect_Constructor(JNIEnv* env) {
+ jniRegisterNativeMethods(env, "java/lang/reflect/Constructor", gMethods, NELEM(gMethods));
+}
+
+} // namespace art
diff --git a/src/java_lang_reflect_Method.cc b/src/java_lang_reflect_Method.cc
index 6ddb436..a988aac 100644
--- a/src/java_lang_reflect_Method.cc
+++ b/src/java_lang_reflect_Method.cc
@@ -25,10 +25,12 @@
namespace {
-// We move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
-// position, because the callers of this function are trying to convey
-// the "traditional" meaning of the flags to their callers.
-uint32_t FixupMethodFlags(uint32_t access_flags) {
+jint Method_getMethodModifiers(JNIEnv* env, jclass, jclass javaDeclaringClass, jobject jmethod, jint slot) {
+ Method* m = Decode<Object*>(env, jmethod)->AsMethod();
+ jint access_flags = m->GetAccessFlags();
+ // We move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
+ // position, because the callers of this function are trying to convey
+ // the "traditional" meaning of the flags to their callers.
access_flags &= ~kAccSynchronized;
if ((access_flags & kAccDeclaredSynchronized) != 0) {
access_flags |= kAccSynchronized;
@@ -36,72 +38,8 @@
return access_flags & kAccMethodFlagsMask;
}
-jint Method_getMethodModifiers(JNIEnv* env, jclass, jclass javaDeclaringClass, jobject jmethod, jint slot) {
- return FixupMethodFlags(Decode<Object*>(env, jmethod)->AsMethod()->GetAccessFlags());
-}
-
-jobject Method_invokeNative(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs, jclass javaDeclaringClass, jobject javaParams, jclass, jint, jboolean) {
- Thread* self = Thread::Current();
- ScopedThreadStateChange tsc(self, Thread::kRunnable);
-
- jmethodID mid = env->FromReflectedMethod(javaMethod);
- Method* m = reinterpret_cast<Method*>(mid);
- Object* receiver = NULL;
- if (!m->IsStatic()) {
- // Check that the receiver is non-null and an instance of the field's declaring class.
- receiver = Decode<Object*>(env, javaReceiver);
- Class* declaringClass = Decode<Class*>(env, javaDeclaringClass);
- if (!VerifyObjectInClass(env, receiver, declaringClass)) {
- return NULL;
- }
-
- // Find the actual implementation of the virtual method.
- m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m);
- }
-
- // Get our arrays of arguments and their types, and check they're the same size.
- ObjectArray<Object>* objects = Decode<ObjectArray<Object>*>(env, javaArgs);
- ObjectArray<Class>* classes = Decode<ObjectArray<Class>*>(env, javaParams);
- int32_t arg_count = (objects != NULL) ? objects->GetLength() : 0;
- if (arg_count != classes->GetLength()) {
- self->ThrowNewException("Ljava/lang/IllegalArgumentException;",
- "wrong number of arguments; expected %d, got %d",
- classes->GetLength(), arg_count);
- return NULL;
- }
-
- // Translate javaArgs to a jvalue[].
- UniquePtr<jvalue[]> args(new jvalue[arg_count]);
- JValue* decoded_args = reinterpret_cast<JValue*>(args.get());
- for (int32_t i = 0; i < arg_count; ++i) {
- Object* arg = objects->Get(i);
- Class* dst_class = classes->Get(i);
- if (dst_class->IsPrimitive()) {
- if (!UnboxPrimitive(env, arg, dst_class, decoded_args[i])) {
- return NULL;
- }
- } else {
- args[i].l = AddLocalReference<jobject>(env, arg);
- }
- }
-
- // Invoke the method.
- JValue value = InvokeWithJValues(env, javaReceiver, mid, args.get());
-
- // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
- if (self->IsExceptionPending()) {
- jthrowable th = env->ExceptionOccurred();
- env->ExceptionClear();
- jclass exception_class = env->FindClass("java/lang/reflect/InvocationTargetException");
- jmethodID mid = env->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V");
- jobject exception_instance = env->NewObject(exception_class, mid, th);
- env->Throw(reinterpret_cast<jthrowable>(exception_instance));
- return NULL;
- }
-
- // Box if necessary and return.
- BoxPrimitive(env, m->GetReturnType(), value);
- return AddLocalReference<jobject>(env, value.l);
+jobject Method_invokeNative(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs, jclass, jobject javaParams, jclass, jint, jboolean) {
+ return InvokeMethod(env, javaMethod, javaReceiver, javaArgs, javaParams);
}
static JNINativeMethod gMethods[] = {
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 8bc5081..fd6d314 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -2837,7 +2837,7 @@
return NULL;
}
} else {
- CHECK_GE(c->GetStatus(), Class::kStatusInitializing);
+ CHECK(c->GetStatus() >= Class::kStatusInitializing) << c->GetStatus() << " " << PrettyMethod(m);
}
std::string detail;
@@ -2848,8 +2848,7 @@
}
// throwing can cause libraries_lock to be reacquired
if (native_method == NULL) {
- Thread::Current()->ThrowNewException("Ljava/lang/UnsatisfiedLinkError;",
- "%s", detail.c_str());
+ Thread::Current()->ThrowNewException("Ljava/lang/UnsatisfiedLinkError;", "%s", detail.c_str());
}
return native_method;
}
diff --git a/src/reflection.cc b/src/reflection.cc
index 3edb9f7..c560053 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -48,6 +48,75 @@
InitBoxingMethod(env, gShort_valueOf, JniConstants::shortClass, "(S)Ljava/lang/Short;");
}
+jobject InvokeMethod(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs, jobject javaParams) {
+ Thread* self = Thread::Current();
+ ScopedThreadStateChange tsc(self, Thread::kRunnable);
+
+ jmethodID mid = env->FromReflectedMethod(javaMethod);
+ Method* m = reinterpret_cast<Method*>(mid);
+
+ Class* declaring_class = m->GetDeclaringClass();
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaring_class, true)) {
+ return NULL;
+ }
+
+ Object* receiver = NULL;
+ if (!m->IsStatic()) {
+ // Check that the receiver is non-null and an instance of the field's declaring class.
+ receiver = Decode<Object*>(env, javaReceiver);
+ if (!VerifyObjectInClass(env, receiver, declaring_class)) {
+ return NULL;
+ }
+
+ // Find the actual implementation of the virtual method.
+ m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m);
+ }
+
+ // Get our arrays of arguments and their types, and check they're the same size.
+ ObjectArray<Object>* objects = Decode<ObjectArray<Object>*>(env, javaArgs);
+ ObjectArray<Class>* classes = Decode<ObjectArray<Class>*>(env, javaParams);
+ int32_t arg_count = (objects != NULL) ? objects->GetLength() : 0;
+ if (arg_count != classes->GetLength()) {
+ self->ThrowNewException("Ljava/lang/IllegalArgumentException;",
+ "wrong number of arguments; expected %d, got %d",
+ classes->GetLength(), arg_count);
+ return NULL;
+ }
+
+ // Translate javaArgs to a jvalue[].
+ UniquePtr<jvalue[]> args(new jvalue[arg_count]);
+ JValue* decoded_args = reinterpret_cast<JValue*>(args.get());
+ for (int32_t i = 0; i < arg_count; ++i) {
+ Object* arg = objects->Get(i);
+ Class* dst_class = classes->Get(i);
+ if (dst_class->IsPrimitive()) {
+ if (!UnboxPrimitive(env, arg, dst_class, decoded_args[i])) {
+ return NULL;
+ }
+ } else {
+ args[i].l = AddLocalReference<jobject>(env, arg);
+ }
+ }
+
+ // Invoke the method.
+ JValue value = InvokeWithJValues(env, javaReceiver, mid, args.get());
+
+ // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
+ if (self->IsExceptionPending()) {
+ jthrowable th = env->ExceptionOccurred();
+ env->ExceptionClear();
+ jclass exception_class = env->FindClass("java/lang/reflect/InvocationTargetException");
+ jmethodID mid = env->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V");
+ jobject exception_instance = env->NewObject(exception_class, mid, th);
+ env->Throw(reinterpret_cast<jthrowable>(exception_instance));
+ return NULL;
+ }
+
+ // Box if necessary and return.
+ BoxPrimitive(env, m->GetReturnType(), value);
+ return AddLocalReference<jobject>(env, value.l);
+}
+
bool VerifyObjectInClass(JNIEnv* env, Object* o, Class* c) {
if (o == NULL) {
jniThrowNullPointerException(env, "receiver for non-static field access was null");
diff --git a/src/reflection.h b/src/reflection.h
index 7256754..2d18331 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -31,6 +31,8 @@
bool ConvertPrimitiveValue(Class* src_class, Class* dst_class, const JValue& src, JValue& dst);
+jobject InvokeMethod(JNIEnv* env, jobject method, jobject receiver, jobject args, jobject params);
+
bool VerifyObjectInClass(JNIEnv* env, Object* o, Class* c);
} // namespace art
diff --git a/src/runtime.cc b/src/runtime.cc
index b1da77d..42bf874 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -365,20 +365,11 @@
Thread::FinishStartup();
- RunImageClinits();
+ class_linker_->RunRootClinits();
StartDaemonThreads();
}
-// initialize classes that have instances in the image but that have
-// <clinit> methods so they could not be initialized by the compiler.
-void Runtime::RunImageClinits() {
- Class* Field_class = class_linker_->FindSystemClass("Ljava/lang/reflect/Field;");
- CHECK(Field_class->FindDeclaredDirectMethod("<clinit>", "()V") != NULL);
- class_linker_->EnsureInitialized(Field_class, true);
- CHECK(!Thread::Current()->IsExceptionPending());
-}
-
void Runtime::StartDaemonThreads() {
signal_catcher_ = new SignalCatcher;
@@ -473,7 +464,7 @@
REGISTER(register_java_lang_VMClassLoader);
//REGISTER(register_java_lang_reflect_AccessibleObject);
REGISTER(register_java_lang_reflect_Array);
- //REGISTER(register_java_lang_reflect_Constructor);
+ REGISTER(register_java_lang_reflect_Constructor);
REGISTER(register_java_lang_reflect_Field);
REGISTER(register_java_lang_reflect_Method);
//REGISTER(register_java_lang_reflect_Proxy);
diff --git a/src/runtime.h b/src/runtime.h
index ee5f524..a6916ac 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -193,7 +193,6 @@
bool Init(const Options& options, bool ignore_unrecognized);
void InitNativeMethods();
void RegisterRuntimeNativeMethods(JNIEnv*);
- void RunImageClinits();
void StartDaemonThreads();
std::string boot_class_path_;
diff --git a/test/SystemMethods/SystemMethods.java b/test/SystemMethods/SystemMethods.java
index 429755f..708a053 100644
--- a/test/SystemMethods/SystemMethods.java
+++ b/test/SystemMethods/SystemMethods.java
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+import java.lang.reflect.*;
+import java.util.*;
+
class SystemMethods {
public static int test0() {
System.logI("hello world");
@@ -84,11 +87,14 @@
return 123;
}
- private static int i = 4;
- private static long j = 0x0123456789abcdefL;
-
- private static float f = 3.14f;
+ private static boolean z = true;
+ private static byte b = 8;
+ private static char c = 'x';
private static double d = Math.PI;
+ private static float f = 3.14f;
+ private static int i = 32;
+ private static long j = 0x0123456789abcdefL;
+ private static short s = 16;
public static int test4() {
String s = "int=" + i + " long=" + j;
@@ -119,7 +125,246 @@
return 123;
}
+ public static void test6() throws Exception {
+ java.lang.reflect.Field f;
+
+ f = SystemMethods.class.getDeclaredField("z");
+ System.out.println(f.getBoolean(null));
+ f = SystemMethods.class.getDeclaredField("b");
+ System.out.println(f.getByte(null));
+ f = SystemMethods.class.getDeclaredField("c");
+ System.out.println(f.getChar(null));
+ f = SystemMethods.class.getDeclaredField("d");
+ System.out.println(f.getDouble(null));
+ f = SystemMethods.class.getDeclaredField("f");
+ System.out.println(f.getFloat(null));
+ f = SystemMethods.class.getDeclaredField("i");
+ System.out.println(f.getInt(null));
+ f = SystemMethods.class.getDeclaredField("j");
+ System.out.println(f.getLong(null));
+ f = SystemMethods.class.getDeclaredField("s");
+ System.out.println(f.getShort(null));
+
+ f = SystemMethods.class.getDeclaredField("z");
+ f.setBoolean(null, false);
+ f = SystemMethods.class.getDeclaredField("b");
+ f.setByte(null, (byte) 7);
+ f = SystemMethods.class.getDeclaredField("c");
+ f.setChar(null, 'y');
+ f = SystemMethods.class.getDeclaredField("d");
+ f.setDouble(null, 2.7);
+ f = SystemMethods.class.getDeclaredField("f");
+ f.setFloat(null, 2.7f);
+ f = SystemMethods.class.getDeclaredField("i");
+ f.setInt(null, 31);
+ f = SystemMethods.class.getDeclaredField("j");
+ f.setLong(null, 63);
+ f = SystemMethods.class.getDeclaredField("s");
+ f.setShort(null, (short) 15);
+
+ f = SystemMethods.class.getDeclaredField("z");
+ System.out.println(f.getBoolean(null));
+ f = SystemMethods.class.getDeclaredField("b");
+ System.out.println(f.getByte(null));
+ f = SystemMethods.class.getDeclaredField("c");
+ System.out.println(f.getChar(null));
+ f = SystemMethods.class.getDeclaredField("d");
+ System.out.println(f.getDouble(null));
+ f = SystemMethods.class.getDeclaredField("f");
+ System.out.println(f.getFloat(null));
+ f = SystemMethods.class.getDeclaredField("i");
+ System.out.println(f.getInt(null));
+ f = SystemMethods.class.getDeclaredField("j");
+ System.out.println(f.getLong(null));
+ f = SystemMethods.class.getDeclaredField("s");
+ System.out.println(f.getShort(null));
+
+ f = SystemMethods.class.getDeclaredField("z");
+ f.set(null, Boolean.valueOf(true));
+ f = SystemMethods.class.getDeclaredField("b");
+ f.set(null, Byte.valueOf((byte) 6));
+ f = SystemMethods.class.getDeclaredField("c");
+ f.set(null, Character.valueOf('z'));
+ f = SystemMethods.class.getDeclaredField("d");
+ f.set(null, Double.valueOf(1.3));
+ f = SystemMethods.class.getDeclaredField("f");
+ f.set(null, Float.valueOf(1.3f));
+ f = SystemMethods.class.getDeclaredField("i");
+ f.set(null, Integer.valueOf(30));
+ f = SystemMethods.class.getDeclaredField("j");
+ f.set(null, Long.valueOf(62));
+ f.set(null, Integer.valueOf(62));
+ f = SystemMethods.class.getDeclaredField("s");
+ f.set(null, Short.valueOf((short) 14));
+
+ f = SystemMethods.class.getDeclaredField("z");
+ System.out.println(f.getBoolean(null));
+ f = SystemMethods.class.getDeclaredField("b");
+ System.out.println(f.getByte(null));
+ f = SystemMethods.class.getDeclaredField("c");
+ System.out.println(f.getChar(null));
+ f = SystemMethods.class.getDeclaredField("d");
+ System.out.println(f.getDouble(null));
+ f = SystemMethods.class.getDeclaredField("f");
+ System.out.println(f.getFloat(null));
+ f = SystemMethods.class.getDeclaredField("i");
+ System.out.println(f.getInt(null));
+ f = SystemMethods.class.getDeclaredField("j");
+ System.out.println(f.getLong(null));
+ f = SystemMethods.class.getDeclaredField("s");
+ System.out.println(f.getShort(null));
+
+ try {
+ f = SystemMethods.class.getDeclaredField("s");
+ f.set(null, Integer.valueOf(14));
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ f = SystemMethods.class.getDeclaredField("z");
+ show(f.get(null));
+ f = SystemMethods.class.getDeclaredField("b");
+ show(f.get(null));
+ f = SystemMethods.class.getDeclaredField("c");
+ show(f.get(null));
+ f = SystemMethods.class.getDeclaredField("d");
+ show(f.get(null));
+ f = SystemMethods.class.getDeclaredField("f");
+ show(f.get(null));
+ f = SystemMethods.class.getDeclaredField("i");
+ show(f.get(null));
+ f = SystemMethods.class.getDeclaredField("j");
+ show(f.get(null));
+ f = SystemMethods.class.getDeclaredField("s");
+ show(f.get(null));
+
+ /*
+ private static boolean z = true;
+ private static byte b = 8;
+ private static char c = 'x';
+ private static double d = Math.PI;
+ private static float f = 3.14f;
+ private static int i = 32;
+ private static long j = 0x0123456789abcdefL;
+ private static short s = 16;
+ */
+ }
+
+ private static void show(Object o) {
+ System.out.println(o + " (" + (o != null ? o.getClass() : "null") + ")");
+ }
+
+ public static void test7() throws Exception {
+ System.out.println(Arrays.toString(String.class.getDeclaredConstructors()));
+ System.out.println(Arrays.toString(String.class.getDeclaredFields()));
+ System.out.println(Arrays.toString(String.class.getDeclaredMethods()));
+
+ System.out.println(Arrays.toString(SystemMethods.class.getInterfaces()));
+ System.out.println(Arrays.toString(String.class.getInterfaces()));
+
+// System.out.println(SystemMethods.class.getModifiers());
+// System.out.println(String.class.getModifiers());
+
+ System.out.println(String.class.isAssignableFrom(Object.class));
+ System.out.println(Object.class.isAssignableFrom(String.class));
+
+ System.out.println(String.class.isInstance("hello"));
+ System.out.println(String.class.isInstance(123));
+
+ java.lang.reflect.Method m;
+
+ m = SystemMethods.class.getDeclaredMethod("IV", int.class);
+ System.out.println(Arrays.toString(m.getParameterTypes()));
+ show(m.invoke(null, 4444));
+ System.out.println(Arrays.toString(m.getParameterTypes()));
+
+ m = SystemMethods.class.getDeclaredMethod("IIV", int.class, int.class);
+ System.out.println(Arrays.toString(m.getParameterTypes()));
+ show(m.invoke(null, 1111, 2222));
+
+ m = SystemMethods.class.getDeclaredMethod("III", int.class, int.class);
+ System.out.println(Arrays.toString(m.getParameterTypes()));
+ show(m.invoke(null, 1111, 2222));
+
+ m = SystemMethods.class.getDeclaredMethod("sumArray", int[].class);
+ System.out.println(Arrays.toString(m.getParameterTypes()));
+ show(m.invoke(null, new int[] { 1, 2, 3, 4 }));
+
+ m = SystemMethods.class.getDeclaredMethod("concat", String[].class);
+ System.out.println(Arrays.toString(m.getParameterTypes()));
+ show(m.invoke(null, (Object) new String[] { "h", "e", "l", "l", "o" }));
+
+ m = SystemMethods.class.getDeclaredMethod("ZBCDFIJSV", boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class, short.class);
+ System.out.println(Arrays.toString(m.getParameterTypes()));
+ show(m.invoke(null, true, (byte) 0, '1', 2, 3, 4, 5, (short) 6));
+
+ m = SystemMethods.class.getDeclaredMethod("ZBCDLFIJSV", boolean.class, byte.class, char.class, double.class, String.class, float.class, int.class, long.class, short.class);
+ System.out.println(Arrays.toString(m.getParameterTypes()));
+ show(m.invoke(null, true, (byte) 0, '1', 2, "hello world", 3, 4, 5, (short) 6));
+
+ try {
+ m = SystemMethods.class.getDeclaredMethod("thrower");
+ System.out.println(Arrays.toString(m.getParameterTypes()));
+ show(m.invoke(null));
+ System.out.println("************* should have thrown!");
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ private static void thrower() {
+ throw new ArithmeticException("surprise!");
+ }
+
+ public static int sumArray(int[] xs) {
+ int result = 0;
+ for (int x : xs) {
+ result += x;
+ }
+ return result;
+ }
+
+ public static String concat(String[] strings) {
+ String result = "";
+ for (String s : strings) {
+ result += s;
+ }
+ return result;
+ }
+
+ public static void IV(int i) {
+ System.out.println(i);
+ }
+
+ public static void IIV(int i, int j) {
+ System.out.println(i + " " + j);
+ }
+
+ public static int III(int i, int j) {
+ System.out.println(i + " " + j);
+ return i + j;
+ }
+
+ public static void ZBCDFIJSV(boolean z, byte b, char c, double d, float f, int i, long l, short s) {
+ System.out.println(z + " " + b + " " + c + " " + d + " " + f + " " + i + " " + l + " " + s);
+ }
+
+ public static void ZBCDLFIJSV(boolean z, byte b, char c, double d, String string, float f, int i, long l, short s) {
+ System.out.println(z + " " + b + " " + c + " " + d + " " + " " + string + " " + f + " " + i + " " + l + " " + s);
+ }
+
+ public static void test8() throws Exception {
+ Constructor<?> ctor;
+
+ ctor = String.class.getConstructor(new Class[0]);
+ show(ctor.newInstance((Object[]) null));
+
+ ctor = String.class.getConstructor(char[].class, int.class, int.class);
+ show(ctor.newInstance(new char[] { 'x', 'y', 'z', '!' }, 1, 2));
+ }
+
public static void main(String[] args) throws Exception {
- test5();
+ test7();
+ test8();
}
}