Mercurial > hg > release > icedtea7-2.2
changeset 2531:666844f8bdb4
Add tapset tests.
* Makefile.am:
Add target to run tapset tests.
* tapset/hotspot_jni.stp.in:
Add notes regarding required JVM option to Get<PrimitiveType>Field
family of probe aliases.
* test/tapset/ClassUnloadedProbeTester.java:
Part of test coverage for hotspot.stp and hotspot_jni.stp tapsets.
* test/tapset/JNIStapTest.c:
Likewise.
* test/tapset/JNITestClass.c:
Likewise.
* test/tapset/JNITestClass.h:
Likewise.
* test/tapset/JNITestClass.java:
Likewise.
* test/tapset/RunWrapper.java:
Likewise.
* test/tapset/StapJNIClassLoader.java:
Likewise.
* test/tapset/StapURLClassLoader.java:
Likewise.
* test/tapset/SystemtapTester.java:
Likewise.
* test/tapset/TestingRunner.java:
Likewise.
* test/tapset/jstaptest.pl:
Wrapper script, compiles and runs tests for tapsets.
author | Jon VanAlten <jon.vanalten@redhat.com> |
---|---|
date | Fri, 23 Mar 2012 14:11:00 +0100 |
parents | 732f30ec8b7b |
children | f67b9f19ee57 |
files | ChangeLog Makefile.am tapset/hotspot_jni.stp.in test/tapset/ClassUnloadedProbeTester.java test/tapset/JNIStapTest.c test/tapset/JNITestClass.c test/tapset/JNITestClass.h test/tapset/JNITestClass.java test/tapset/RunWrapper.java test/tapset/StapJNIClassLoader.java test/tapset/StapURLClassLoader.java test/tapset/SystemtapTester.java test/tapset/TestingRunner.java test/tapset/jstaptest.pl |
diffstat | 14 files changed, 3713 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Fri Mar 16 13:15:15 2012 +0100 +++ b/ChangeLog Fri Mar 23 14:11:00 2012 +0100 @@ -1,3 +1,33 @@ +2012-03-23 Jon VanAlten <jon.vanalten@redhat.com> + + * Makefile.am: + Add target to run tapset tests. + * tapset/hotspot_jni.stp.in: + Add notes regarding required JVM option to Get<PrimitiveType>Field + family of probe aliases. + * test/tapset/ClassUnloadedProbeTester.java: + Part of test coverage for hotspot.stp and hotspot_jni.stp tapsets. + * test/tapset/JNIStapTest.c: + Likewise. + * test/tapset/JNITestClass.c: + Likewise. + * test/tapset/JNITestClass.h: + Likewise. + * test/tapset/JNITestClass.java: + Likewise. + * test/tapset/RunWrapper.java: + Likewise. + * test/tapset/StapJNIClassLoader.java: + Likewise. + * test/tapset/StapURLClassLoader.java: + Likewise. + * test/tapset/SystemtapTester.java: + Likewise. + * test/tapset/TestingRunner.java: + Likewise. + * test/tapset/jstaptest.pl: + Wrapper script, compiles and runs tests for tapsets. + 2012-03-16 Mark Wielaard <mjw@redhat.com> * tapset/jstack.stp.in: Change symbolOopDesc to Symbol to accomodate
--- a/Makefile.am Fri Mar 16 13:15:15 2012 +0100 +++ b/Makefile.am Fri Mar 23 14:11:00 2012 +0100 @@ -725,9 +725,16 @@ all-local: icedtea-stage2 -check-local: jtregcheck +check-local: jtregcheck check-tapset -clean-local: clean-jtreg clean-jtreg-reports clean-pulse-java \ +clean-tests: clean-jtreg clean-tapset-report + if [ $(abs_top_srcdir) != $(abs_top_builddir) ] ; then \ + if [ -e test ] ; then \ + rmdir test ; \ + fi \ + fi + +clean-local: clean-tests clean-jtreg-reports clean-pulse-java \ clean-icedtea clean-icedtea-boot clean-clone clean-clone-boot \ clean-bootstrap-directory-stage1 clean-bootstrap-directory-stage2 \ clean-bootstrap-directory-symlink-stage1 clean-bootstrap-directory-symlink-stage2 \ @@ -762,7 +769,8 @@ clean-rt hotspot hotspot-helper clean-jtreg clean-jtreg-reports \ jtregcheck clean-remove-intree-libraries \ clean-jamvm clean-extract-jamvm clean-add-jamvm clean-add-jamvm-debug \ - clean-extract-hotspot clean-sanitise-openjdk + clean-extract-hotspot clean-sanitise-openjdk \ + clean-tests clean-tapset-report env: @echo 'unset JAVA_HOME' @@ -2266,6 +2274,19 @@ $(jtreg_processes); \ fi +check-tapset: +if ENABLE_SYSTEMTAP + $(abs_top_srcdir)/test/tapset/jstaptest.pl \ + -B $(BUILD_OUTPUT_DIR) -A $(BUILD_ARCH_DIR) \ + -S $(abs_top_srcdir)/test/tapset \ + -o test/check-stap.log +endif + +clean-tapset-report: +if ENABLE_SYSTEMTAP + rm -f test/check-stap.log +endif + # Support classes for non-OpenJDK bootstraps rt-source-files.txt: $(OPENJDK_BOOT_TREE)
--- a/tapset/hotspot_jni.stp.in Fri Mar 16 13:15:15 2012 +0100 +++ b/tapset/hotspot_jni.stp.in Fri Mar 23 14:11:00 2012 +0100 @@ -3472,6 +3472,7 @@ /* hotspot.jni.GetBooleanField * Get non-static jboolean field value. + * NEEDS: -XX:-UseFastJNIAccessors * * env - JNIEnv pointer. * obj - jobject. @@ -3490,6 +3491,7 @@ /* hotspot.jni.GetBooleanField.return * Get non-static jboolean field value. Return. + * NEEDS: -XX:-UseFastJNIAccessors * * ret - jboolean value. */ @@ -3569,6 +3571,7 @@ /* hotspot.jni.GetByteField * Get non-static jbyte field value. + * NEEDS: -XX:-UseFastJNIAccessors * * env - JNIEnv pointer. * obj - jobject. @@ -3587,6 +3590,7 @@ /* hotspot.jni.GetByteField.return * Get non-static jbyte field value. Return. + * NEEDS: -XX:-UseFastJNIAccessors * * ret - jbyte value. */ @@ -3666,6 +3670,7 @@ /* hotspot.jni.GetCharField * Get non-static jchar field value. + * NEEDS: -XX:-UseFastJNIAccessors * * env - JNIEnv pointer. * obj - jobject. @@ -3684,6 +3689,7 @@ /* hotspot.jni.GetCharField.return * Get non-static jchar field value. Return. + * NEEDS: -XX:-UseFastJNIAccessors * * ret - jchar value. */ @@ -3701,7 +3707,7 @@ * * vmbuf - Pointer to JavaVM pointer. * buflen - Max number of vms returned. - * nvms - Number of JavaVMs returned. + * nvms - Pointer to where the number of created JavaVMs will be returned. */ probe hotspot.jni.GetCreatedJavaVMs = process("@ABS_CLIENT_LIBJVM_SO@").mark("GetCreatedJavaVMs__entry"), @@ -3711,7 +3717,7 @@ vmbuf = $arg1 buflen = $arg2 nvms = $arg3 - probestr = sprintf("%s(vmbuf=0x%x,buflen=%d,nvms=%d)", name, vmbuf, buflen, nvms) + probestr = sprintf("%s(vmbuf=0x%x,buflen=%d,nvms=0x%x)", name, vmbuf, buflen, nvms) } /* hotspot.jni.GetCreatedJavaVMs.return @@ -3883,6 +3889,7 @@ /* hotspot.jni.GetDoubleField * Get non-static jdouble field value. + * NEEDS: -XX:-UseFastJNIAccessors * * env - JNIEnv pointer. * obj - jobject. @@ -3901,6 +3908,7 @@ /* hotspot.jni.GetDoubleField.return * Get non-static jdouble field value. Return. + * NEEDS: -XX:-UseFastJNIAccessors */ probe hotspot.jni.GetDoubleField.return = process("@ABS_CLIENT_LIBJVM_SO@").mark("GetDoubleField__return"), @@ -4043,6 +4051,7 @@ /* hotspot.jni.GetFloatField * Get non-static jfloat field value. + * NEEDS: -XX:-UseFastJNIAccessors * * env - JNIEnv pointer. * obj - jobject. @@ -4061,6 +4070,7 @@ /* hotspot.jni.GetFloatField.return * Get non-static jfloat field value. Return. + * NEEDS: -XX:-UseFastJNIAccessors */ probe hotspot.jni.GetFloatField.return = process("@ABS_CLIENT_LIBJVM_SO@").mark("GetFloatField__return"), @@ -4137,6 +4147,7 @@ /* hotspot.jni.GetIntField * Get non-static jint field value. + * NEEDS: -XX:-UseFastJNIAccessors * * env - JNIEnv pointer. * obj - jobject. @@ -4155,6 +4166,7 @@ /* hotspot.jni.GetIntField.return * Get non-static jint field value. Return. + * NEEDS: -XX:-UseFastJNIAccessors * * ret - jint value. */ @@ -4264,6 +4276,7 @@ /* hotspot.jni.GetLongField * Get non-static jlong field value. + * NEEDS: -XX:-UseFastJNIAccessors * * env - JNIEnv pointer. * obj - jobject. @@ -4282,6 +4295,7 @@ /* hotspot.jni.GetLongField.return * Get non-static jlong field value. Return. + * NEEDS: -XX:-UseFastJNIAccessors * * ret - jlong value. */ @@ -4551,6 +4565,7 @@ /* hotspot.jni.GetShortField * Get non-static jshort field value. + * NEEDS: -XX:-UseFastJNIAccessors * * env - JNIEnv pointer. * obj - jobject. @@ -4569,6 +4584,7 @@ /* hotspot.jni.GetShortField.return * Get non-static jshort field value. Return. + * NEEDS: -XX:-UseFastJNIAccessors * * ret - jshort value. */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/ClassUnloadedProbeTester.java Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,38 @@ +package staptest; + +class ClassUnloadedProbeTester { + private int myField; + long total; + static ClassUnloadedProbeTester tester; + + public static void main(String[] args) { + long total = 0; + for (int i = 1; i < 105; i++) { + tester = new ClassUnloadedProbeTester(); + tester.runner(tester, i); + if (total != tester.total) + total += tester.getField(); + } + } + + void runner(ClassUnloadedProbeTester run, int j) { + for (int i = 1; i < 105; i++) { + run.setField(i); + total += tester.getField(); + } + total += j; + } + + public ClassUnloadedProbeTester() { + myField = 500; + } + + public int getField() { + return myField; + } + + public void setField(int newValue) { + myField = newValue; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/JNIStapTest.c Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,2107 @@ +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "jni.h" +#include "JNITestClass.h" + +/* Longer than any known good argument. */ +#define MAX_ARG_LEN 128 +/* Arbitrary length. Some arrays are assigned with literals, so do not change + * this without examining the source carefully. + */ +#define TEST_ARRAY_LEN 5 + +/* Arguments for run_attach_current_thread. */ +#define DAEMON 1 +#define NOT_DAEMON 2 + +/* Avoiding repeated inline string constants. */ +char* const ALLOC_OBJECT = "AllocObject"; +char* const ATTACH_CURRENT_THREAD_AS_DAEMON = "AttachCurrentThreadAsDaemon"; +char* const ATTACH_CURRENT_THREAD = "AttachCurrentThread"; +char* const CALL = "Call"; +char* const CREATE_JAVA_VM = "CreateJavaVM"; +char* const DEFINE_CLASS = "DefineClass"; +char* const DELETE_GLOBAL_REF = "DeleteGlobalRef"; +char* const DELETE_LOCAL_REF = "DeleteLocalRef"; +char* const DELETE_WEAK_GLOBAL_REF = "DeleteWeakGlobalRef"; +char* const DESTROY_JAVA_VM = "DestroyJavaVM"; +char* const DETACH_CURRENT_THREAD = "DetachCurrentThread"; +char* const ENSURE_LOCAL_CAPACITY = "EnsureLocalCapacity"; +char* const EXCEPTION_CHECK = "ExceptionCheck"; +char* const EXCEPTION_CLEAR = "ExceptionClear"; +char* const EXCEPTION_DESCRIBE = "ExceptionDescribe"; +char* const EXCEPTION_OCCURRED = "ExceptionOccurred"; +char* const FATAL_ERROR = "FatalError"; +char* const FIND_CLASS = "FindClass"; +char* const FROM_REFLECTED_FIELD = "FromReflectedField"; +char* const FROM_REFLECTED_METHOD = "FromReflectedMethod"; +char* const GET_ARRAY_LENGTH = "GetArrayLength"; +char* const GET_CREATED_JAVA_VMS = "GetCreatedJavaVMs"; +char* const GET_DEFAULT_JAVA_VM_INIT_ARGS = "GetDefaultJavaVMInitArgs"; +char* const GET_DIRECT_BUFFER_ADDRESS = "GetDirectBufferAddress"; +char* const GET_DIRECT_BUFFER_CAPACITY = "GetDirectBufferCapacity"; +char* const GET = "Get"; +char* const GET_ENV = "GetEnv"; +char* const GET_FIELD_ID = "GetFieldID"; +char* const GET_JAVA_VM = "GetJavaVM"; +char* const GET_METHOD_ID = "GetMethodID"; +char* const GET_OBJECT_CLASS = "GetObjectClass"; +char* const GET_OBJECT_REF_TYPE = "GetObjectRefType"; +char* const GET_PRIMITIVE_ARRAY_CRITICAL = "GetPrimitiveArrayCritical"; +char* const GET_STATIC_FIELD_ID = "GetStaticFieldID"; +char* const GET_STATIC_METHOD_ID = "GetStaticMethodID"; +char* const GET_STRING = "GetString"; +char* const GET_STRING_UTF = "GetStringUTF"; +char* const GET_SUPERCLASS = "GetSuperclass"; +char* const GET_VERSION = "GetVersion"; +char* const IS_ASSIGNABLE_FROM = "IsAssignableFrom"; +char* const IS_INSTANCE_OF = "IsInstanceOf"; +char* const IS_SAME_OBJECT = "IsSameObject"; +char* const MONITOR = "Monitor"; +char* const NEW = "New"; +char* const NEW_DIRECT_BYTE_BUFFER = "NewDirectByteBuffer"; +char* const NEW_GLOBAL_REF = "NewGlobalRef"; +char* const NEW_LOCAL_REF = "NewLocalRef"; +char* const NEW_OBJECT_A = "NewObjectA"; +char* const NEW_OBJECT = "NewObject"; +char* const NEW_OBJECT_V = "NewObjectV"; +char* const NEW_STRING = "NewString"; +char* const NEW_STRING_UTF = "NewStringUTF"; +char* const NEW_WEAK_GLOBAL_REF = "NewWeakGlobalRef"; +char* const POP_LOCAL_FRAME = "PopLocalFrame"; +char* const PUSH_LOCAL_FRAME = "PushLocalFrame"; +char* const REGISTER_NATIVES = "RegisterNatives"; +char* const RELEASE = "Release"; +char* const RELEASE_PRIMITIVE_ARRAY_CRITICAL = "ReleasePrimitiveArrayCritical"; +char* const RELEASE_STRING_CHARS = "ReleaseStringChars"; +char* const RELEASE_STRING_CRITICAL = "ReleaseStringCritical"; +char* const RELEASE_STRING_UTF_CHARS = "ReleaseStringUTFChars"; +char* const SET = "Set"; +char* const THROW = "Throw"; +char* const THROW_NEW = "ThrowNew"; +char* const TO_REFLECTED_FIELD = "ToReflectedField"; +char* const TO_REFLECTED_METHOD = "ToReflectedMethod"; +char* const UNREGISTER_NATIVES = "UnregisterNatives"; + +char* const FIELD = "Field"; +char* const ARRAY = "Array"; +char* const STATIC = "Static"; +char* const NONVIRTUAL = "Nonvirtual"; +char* const DIRECT = "Direct"; +char* const BOOLEAN = "Boolean"; +char* const BYTE = "Byte"; +char* const CHAR = "Char"; +char* const DOUBLE = "Double"; +char* const FLOAT = "Float"; +char* const INT = "Int"; +char* const LONG = "Long"; +char* const OBJECT = "Object"; +char* const SHORT = "Short"; +char* const VOID = "Void"; + +char* const TEST_CLASS = "staptest/JNITestClass"; + +/* These functions defined below. */ +void bad_usage(); +void* run_attach_current_thread(void* style); + +int get_type_and_modifier(char* arg, char** type_p, char** mod_p); + +jboolean is_field_op(char* arg); +jboolean is_array_op(char* arg); + +jint create_java_vm_wrap(JavaVMInitArgs* args); + +jobject new_object_v_wrap(JNIEnv* env_, jclass* class_p, + jmethodID* construct, ...); + +jboolean boolean_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); +jbyte byte_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); +jchar char_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); +jdouble double_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); +jfloat float_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); +jint int_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); +jlong long_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); +jobject object_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); +jshort short_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); +void void_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...); + +jboolean nonvirtual_boolean_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); +jbyte nonvirtual_byte_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); +jchar nonvirtual_char_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); +jdouble nonvirtual_double_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); +jfloat nonvirtual_float_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); +jint nonvirtual_int_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); +jlong nonvirtual_long_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); +jobject nonvirtual_object_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); +jshort nonvirtual_short_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); +void nonvirtual_void_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...); + +jboolean static_boolean_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); +jbyte static_byte_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); +jchar static_char_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); +jdouble static_double_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); +jfloat static_float_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); +jint static_int_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); +jlong static_long_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); +jobject static_object_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); +jshort static_short_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); +void static_void_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...); + +/* We don't want to have to pass these around all the time, so make them global. + * This would probably be a Very Bad Idea in real JNI code. + */ +JavaVM* jvm; +JNIEnv *env; + +int main(int argc, char *argv[]) { + + pthread_t attach_thread; + + if (argc != 2) { + bad_usage("No argument specified."); + exit(1); + } + int arglen = (int) strlen(argv[1]); + if (arglen > MAX_ARG_LEN) { + bad_usage("Argument too long."); + exit(1); + } + char* safe_arg = (char*) malloc(sizeof(char)*(MAX_ARG_LEN + 1)); + strncpy(safe_arg, argv[1], MAX_ARG_LEN); + /* Copy into a larger array so we can strncmp to our string constants + * without the risk of running past the end of the string. + */ +/* This is a gigantic if-else if-else block. Each JNI function (or, where + * appropriate, groups of related JNI functions) are called independently, as + * determined by the argument to this program, in order to trigger the + * corresponding systemtap/dtrace probes. + */ + if ((strncmp(safe_arg, CREATE_JAVA_VM, + strlen(CREATE_JAVA_VM)) == 0) || + (strncmp(safe_arg, DESTROY_JAVA_VM, + strlen(DESTROY_JAVA_VM)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + /* No further action needed. */ + goto end_vm; + } else if (strncmp(safe_arg, FATAL_ERROR, strlen(FATAL_ERROR)) == 0) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + (*env)->FatalError(env, "Intentional Crash: Ignore."); + exit(-1); + } else if (strncmp(safe_arg, GET_VERSION, strlen(GET_VERSION)) == 0) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + (*env)->GetVersion(env); + } else if (strncmp(safe_arg, GET_ENV, strlen(GET_ENV)) == 0) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + JNIEnv *tmp_env; + (*jvm)->GetEnv(jvm, (void**)&tmp_env, JNI_VERSION_1_6); + } else if (strncmp(safe_arg, GET_DEFAULT_JAVA_VM_INIT_ARGS, + strlen(GET_DEFAULT_JAVA_VM_INIT_ARGS)) == 0) { + JavaVMInitArgs vm_args; + vm_args.version = JNI_VERSION_1_6; + JNI_GetDefaultJavaVMInitArgs(&vm_args); + if (safe_arg != NULL) { + free(safe_arg); + safe_arg = NULL; + } + exit(0); + } else if (strncmp(safe_arg, GET_JAVA_VM, + strlen(GET_JAVA_VM)) == 0) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + JavaVM* vm_pointer; + (*env)->GetJavaVM(env, &vm_pointer); + } else if (strncmp(safe_arg, DEFINE_CLASS, strlen(DEFINE_CLASS)) == 0) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jclass loaderClass = (*env)->FindClass(env, "staptest/StapJNIClassLoader"); + if (loaderClass == NULL) { + /* Bail out, cannot find class. */ + goto end_vm; + } + jmethodID loadConstructor = (*env)->GetMethodID(env, loaderClass, + "<init>", "()V"); + if (loadConstructor == NULL) { + /* Bail out, cannot find constructor. */ + goto end_vm; + } + jobject loader = (*env)->NewObject(env, loaderClass, loadConstructor); + if (loader == NULL) { + /* Bail out, cannot create loader. */ + goto end_vm; + } + int class_fildes = open("./staptest/JNITestClass.class", O_RDONLY|O_NONBLOCK); + if (class_fildes == -1) { + /* Bail out, cannot open class file. */ + goto end_vm; + } + struct stat classfile_stats; + int r_val = fstat(class_fildes, &classfile_stats); + if (r_val != 0) { + /* Bail out, cannot determine classfile size. */ + goto end_vm; + } + ssize_t classfile_size = (ssize_t) classfile_stats.st_size; + jbyte* classfile_buf = malloc(sizeof(jbyte)*classfile_size); + ssize_t total_bytes_read = 0; + /* Ensure entire file is read in case of interrupts. */ + while (total_bytes_read < classfile_size) { + size_t bytes_needed = (size_t) classfile_size - (size_t) total_bytes_read; + void* buf_start = (void*) classfile_buf + total_bytes_read; + ssize_t bytes_read = pread(class_fildes, buf_start, + bytes_needed, (off_t) total_bytes_read); + if (bytes_read <= 0) { + /* Bail out, reading from file blocked or unexpected EOF */ + if (classfile_buf != NULL) { + free(classfile_buf); + classfile_buf = NULL; + } + goto end_vm; + } + total_bytes_read += bytes_read; + } + jclass testClass = (*env)->DefineClass(env, TEST_CLASS, loader, + classfile_buf, (jsize) classfile_size); + if (classfile_buf != NULL) { + free(classfile_buf); + classfile_buf = NULL; + } + } else if ((strncmp(safe_arg, ENSURE_LOCAL_CAPACITY, + strlen(ENSURE_LOCAL_CAPACITY)) == 0) || + (strncmp(safe_arg, PUSH_LOCAL_FRAME, + strlen(PUSH_LOCAL_FRAME)) == 0) || + (strncmp(safe_arg, POP_LOCAL_FRAME, + strlen(POP_LOCAL_FRAME)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jint rval = (*env)->PushLocalFrame(env, (jint) 10); + if (rval == JNI_OK) { + (*env)->EnsureLocalCapacity(env, (jint) 10); + (*env)->PopLocalFrame(env, NULL); + } + } else if ((strncmp(safe_arg, NEW_OBJECT, strlen(NEW_OBJECT)) == 0) && + (strlen(safe_arg) == strlen(NEW_OBJECT))) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jclass testClass = (*env)->FindClass(env, TEST_CLASS); + if (testClass == NULL) { + /* Bail out, cannot find class. */ + goto end_vm; + } + jmethodID constructor = (*env)->GetMethodID(env, testClass, + "<init>", "()V"); + if (constructor == NULL) { + /* Bail out, cannot find constructor. */ + goto end_vm; + } + jobject testInstance = (*env)->NewObject(env, testClass, constructor); + } else if ((strncmp(safe_arg, NEW_OBJECT_A, strlen(NEW_OBJECT_A)) == 0) && + (strlen(safe_arg) == strlen(NEW_OBJECT_A))) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jclass testClass = (*env)->FindClass(env, TEST_CLASS); + if (testClass == NULL) { + /* Bail out, cannot find class. */ + goto end_vm; + } + jmethodID constructor = (*env)->GetMethodID(env, testClass, + "<init>", "()V"); + if (constructor == NULL) { + /* Bail out, cannot find constructor. */ + goto end_vm; + } + jobject testInstance = (*env)->NewObjectA(env, testClass, + constructor, NULL); + } else if (strncmp(safe_arg, NEW_OBJECT_V, strlen(NEW_OBJECT_V)) == 0) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jclass testClass = (*env)->FindClass(env, TEST_CLASS); + if (testClass == NULL) { + /* Bail out, cannot find class. */ + goto end_vm; + } + jmethodID constructor = (*env)->GetMethodID(env, testClass, + "<init>", "()V"); + if (constructor == NULL) { + /* Bail out, cannot find constructor. */ + goto end_vm; + } + jobject testInstance = new_object_v_wrap(env, &testClass, &constructor); + } else if ((strncmp(safe_arg, GET_ARRAY_LENGTH, + strlen(GET_ARRAY_LENGTH)) == 0) || + (strncmp(safe_arg, GET_PRIMITIVE_ARRAY_CRITICAL, + strlen(GET_PRIMITIVE_ARRAY_CRITICAL)) == 0) || + (strncmp(safe_arg, RELEASE_PRIMITIVE_ARRAY_CRITICAL, + strlen(RELEASE_PRIMITIVE_ARRAY_CRITICAL)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jbyteArray byte_array = (*env)->NewByteArray(env, (jsize) TEST_ARRAY_LEN); + jsize byte_array_len = (*env)->GetArrayLength(env, (jarray) byte_array); + void* primitive_array = (*env)->GetPrimitiveArrayCritical(env, + (jarray) byte_array, NULL); + if (primitive_array == NULL) { + /* JVM out of memory, don't try to release. */ + goto end_vm; + } + (*env)->ReleasePrimitiveArrayCritical(env, (jarray) byte_array, + primitive_array, JNI_ABORT); + } else if (strncmp(safe_arg+3, DIRECT, strlen(DIRECT)) == 0) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + void* some_space = malloc((size_t) MAX_ARG_LEN); + jobject byte_buffer = (*env)->NewDirectByteBuffer(env, some_space, + (jlong) MAX_ARG_LEN); + void* pointer_to_some_space = (*env)->GetDirectBufferAddress(env, + byte_buffer); + jlong some_space_capacity = (*env)->GetDirectBufferCapacity(env, + byte_buffer); + if (some_space != NULL) { + free(some_space); + some_space = NULL; + } + } else if ((strncmp(safe_arg, THROW, strlen(THROW)) == 0) || + (strncmp(safe_arg, EXCEPTION_CHECK, + strlen(EXCEPTION_CHECK)) == 0) || + (strncmp(safe_arg, EXCEPTION_CLEAR, + strlen(EXCEPTION_CLEAR)) == 0) || + (strncmp(safe_arg, EXCEPTION_DESCRIBE, + strlen(EXCEPTION_DESCRIBE)) == 0) || + (strncmp(safe_arg, EXCEPTION_OCCURRED, + strlen(EXCEPTION_OCCURRED)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jclass exceptionClass = (*env)->FindClass(env, "java/lang/Exception"); + if (exceptionClass == NULL) { + /* Bail out, cannot find class. */ + goto end_vm; + } + jmethodID constructor = (*env)->GetMethodID(env, exceptionClass, + "<init>", "()V"); + if (constructor == NULL) { + /* Bail out, cannot find constructor. */ + goto end_vm; + } + jthrowable anException = (jthrowable) (*env)->NewObject(env, + exceptionClass, constructor); + if (anException == NULL) { + /* Bail out, cannot create exception. */ + goto end_vm; + } + jint r_val = (*env)->Throw(env, anException); + if (r_val != 0) { + /* Bail out, couldn't throw exception. */ + goto end_vm; + } + jboolean exception_thrown = (*env)->ExceptionCheck(env); + if (exception_thrown == JNI_FALSE) { + /* Huh? Should be true. */ + goto end_vm; + } + (*env)->ExceptionClear(env); + r_val = (*env)->ThrowNew(env, exceptionClass, "This exception is for testing purposes only."); + anException = (*env)->ExceptionOccurred(env); + if (anException == NULL) { + goto end_vm; + } + (*env)->ExceptionClear(env); + /* We don't actually want to see output, so we clear exception first. */ + (*env)->ExceptionDescribe(env); + } else if ((strncmp(safe_arg, REGISTER_NATIVES, + strlen(REGISTER_NATIVES)) == 0) || + (strncmp(safe_arg, UNREGISTER_NATIVES, + strlen(UNREGISTER_NATIVES)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jclass testClass = (*env)->FindClass(env, TEST_CLASS); + if (testClass == NULL) { + /* Bail out, cannot find class. */ + goto end_vm; + } + JNINativeMethod jni_method; + jni_method.name = "doNothing"; + jni_method.signature = "()V"; + jni_method.fnPtr = &Java_JNITestClass_doNothing; + jint r_val = (*env)->RegisterNatives(env, testClass, &jni_method, (jint) 1); + if (r_val != 0) { + goto end_vm; + } + r_val = (*env)->UnregisterNatives(env, testClass); + } else if ((strncmp(safe_arg, ATTACH_CURRENT_THREAD_AS_DAEMON, + strlen(ATTACH_CURRENT_THREAD_AS_DAEMON)) == 0) || + (strncmp(safe_arg, GET_CREATED_JAVA_VMS, + strlen(GET_CREATED_JAVA_VMS)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + int rval; + int style = (int) DAEMON; + rval = pthread_create(&attach_thread, NULL, + run_attach_current_thread, &style); + if (rval == 0) { + pthread_join(attach_thread, NULL); + } + } else if ((strncmp(safe_arg, ATTACH_CURRENT_THREAD, + strlen(ATTACH_CURRENT_THREAD)) == 0) || + (strncmp(safe_arg, DETACH_CURRENT_THREAD, + strlen(DETACH_CURRENT_THREAD)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + int rval; + int style = (int) NOT_DAEMON; + rval = pthread_create(&attach_thread, NULL, + run_attach_current_thread, &style); + if (rval == 0) { + pthread_join(attach_thread, NULL); + } + } else if ((strncmp(safe_arg, ALLOC_OBJECT, + strlen(ALLOC_OBJECT)) == 0) || +/* A bunch of jni functions having to do with classes and references. */ + (strncmp(safe_arg, DELETE_GLOBAL_REF, + strlen(DELETE_GLOBAL_REF)) == 0) || + (strncmp(safe_arg, DELETE_LOCAL_REF, + strlen(DELETE_LOCAL_REF)) == 0) || + (strncmp(safe_arg, DELETE_WEAK_GLOBAL_REF, + strlen(DELETE_WEAK_GLOBAL_REF)) == 0) || + (strncmp(safe_arg, FIND_CLASS, + strlen(FIND_CLASS)) == 0) || + (strncmp(safe_arg, GET_FIELD_ID, + strlen(GET_FIELD_ID)) == 0) || + (strncmp(safe_arg, GET_METHOD_ID, + strlen(GET_METHOD_ID)) == 0) || + (strncmp(safe_arg, GET_OBJECT_CLASS, + strlen(GET_OBJECT_CLASS)) == 0) || + (strncmp(safe_arg, GET_OBJECT_REF_TYPE, + strlen(GET_OBJECT_REF_TYPE)) == 0) || + (strncmp(safe_arg, GET_STATIC_FIELD_ID, + strlen(GET_STATIC_FIELD_ID)) == 0) || + (strncmp(safe_arg, GET_STATIC_METHOD_ID, + strlen(GET_STATIC_METHOD_ID)) == 0) || + (strncmp(safe_arg, GET_SUPERCLASS, + strlen(GET_SUPERCLASS)) == 0) || + (strncmp(safe_arg, IS_ASSIGNABLE_FROM, + strlen(IS_ASSIGNABLE_FROM)) == 0) || + (strncmp(safe_arg, IS_INSTANCE_OF, + strlen(IS_INSTANCE_OF)) == 0) || + (strncmp(safe_arg, IS_SAME_OBJECT, + strlen(IS_SAME_OBJECT)) == 0) || + (strncmp(safe_arg, NEW_GLOBAL_REF, + strlen(NEW_GLOBAL_REF)) == 0) || + (strncmp(safe_arg, NEW_LOCAL_REF, + strlen(NEW_LOCAL_REF)) == 0) || + (strncmp(safe_arg, NEW_WEAK_GLOBAL_REF, + strlen(NEW_WEAK_GLOBAL_REF)) == 0) || + (strncmp(safe_arg, TO_REFLECTED_FIELD, + strlen(TO_REFLECTED_FIELD)) == 0) || + (strncmp(safe_arg, FROM_REFLECTED_FIELD, + strlen(FROM_REFLECTED_FIELD)) == 0) || + (strncmp(safe_arg, TO_REFLECTED_METHOD, + strlen(TO_REFLECTED_METHOD)) == 0) || + (strncmp(safe_arg, FROM_REFLECTED_METHOD, + strlen(FROM_REFLECTED_METHOD)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jclass testClass = (*env)->FindClass(env, TEST_CLASS); + if (testClass == NULL) { + /* Bail out, cannot find class. */ + goto end_vm; + } + jobject testClassInstance = (*env)->AllocObject(env, testClass); + jclass aClass = (*env)->GetObjectClass(env, testClassInstance); + jclass superClass = (*env)->GetSuperclass(env, aClass); + jboolean jboolrval = (*env)->IsAssignableFrom(env, testClass, aClass); + jboolrval = (*env)->IsInstanceOf(env, testClassInstance, testClass); + jfieldID myBoolean = (*env)->GetFieldID(env, testClass, "myBoolean", "Z"); + jobject myBooleanRef = (*env)->ToReflectedField(env, testClass, myBoolean, + (jboolean) JNI_FALSE); + jfieldID myBoolean2 = (*env)->FromReflectedField(env, myBooleanRef); + jmethodID getBoolean = (*env)->GetMethodID(env, testClass, + "getBoolean", "()Z"); + jobject getBooleanRef = (*env)->ToReflectedMethod(env, testClass, + getBoolean, (jboolean) JNI_FALSE); + jmethodID getBoolean2 = (*env)->FromReflectedMethod(env, getBooleanRef); + jfieldID myStaticBoolean = (*env)->GetStaticFieldID(env, testClass, + "myStaticBoolean", "Z"); + jmethodID getStaticBoolean = (*env)->GetStaticMethodID(env, testClass, + "getStaticBoolean", "()Z"); + jobject testClassLocal = (*env)->NewLocalRef(env, testClassInstance); + jobject testClassGlobal = (*env)->NewGlobalRef(env, testClassInstance); + jobject testClassWeakGlobal = (*env)->NewWeakGlobalRef(env, + testClassInstance); + jboolrval = (*env)->IsSameObject(env, testClassGlobal, testClassWeakGlobal); + jobjectRefType refType = (*env)->GetObjectRefType(env, testClassGlobal); + (*env)->DeleteGlobalRef(env, testClassGlobal); + (*env)->DeleteWeakGlobalRef(env, testClassWeakGlobal); + (*env)->DeleteLocalRef(env, testClassLocal); + } else if (strncmp(safe_arg, MONITOR, strlen(MONITOR)) == 0) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + jclass testClass = (*env)->FindClass(env, TEST_CLASS); + if (testClass == NULL) { + /* Bail out, cannot find class. */ + goto end_vm; + } + jmethodID constructor = (*env)->GetMethodID(env, testClass, + "<init>", "()V"); + if (constructor == NULL) { + /* Bail out, cannot find constructor. */ + goto end_vm; + } + jobject testInstance = (*env)->NewObject(env, testClass, constructor); + (*env)->MonitorEnter(env, testInstance); + (*env)->MonitorExit(env, testInstance); + } else if ((strncmp(safe_arg, GET_STRING_UTF, + strlen(GET_STRING_UTF)) == 0) || + (strncmp(safe_arg, NEW_STRING_UTF, + strlen(NEW_STRING_UTF)) == 0) || + (strncmp(safe_arg, RELEASE_STRING_UTF_CHARS, + strlen(RELEASE_STRING_UTF_CHARS)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + char string_chars[6] = {0x57,0x4F,0x52,0x44,0xC0,0x80}; + jstring aString = (*env)->NewStringUTF(env, string_chars); + jsize str_len = (*env)->GetStringUTFLength(env, aString); + char string_buf[2]; + (*env)->GetStringUTFRegion(env, aString, (jsize) 1, (jsize) 2, string_buf); + const jbyte* str_pointer = (*env)->GetStringUTFChars(env, aString, NULL); + (*env)->ReleaseStringUTFChars(env, aString, (char*) str_pointer); + } else if ((strncmp(safe_arg, GET_STRING, + strlen(GET_STRING)) == 0) || + (strncmp(safe_arg, NEW_STRING, + strlen(NEW_STRING)) == 0) || + (strncmp(safe_arg, RELEASE_STRING_CHARS, + strlen(RELEASE_STRING_CHARS)) == 0) || + (strncmp(safe_arg, RELEASE_STRING_CRITICAL, + strlen(RELEASE_STRING_CRITICAL)) == 0)) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + /* Long way to say "WORD" in Unicode: */ + jchar string_chars[4] = {(jchar)0x57,(jchar)0x4F,(jchar)0x52,(jchar)0x44}; + jstring aString = (*env)->NewString(env, string_chars, (jsize) 4); + jsize str_len = (*env)->GetStringLength(env, aString); + jchar string_buf[2]; + (*env)->GetStringRegion(env, aString, (jsize) 1, (jsize) 2, string_buf); + const jchar* str_pointer = (*env)->GetStringChars(env, aString, NULL); + (*env)->ReleaseStringChars(env, aString, str_pointer); + str_pointer = (*env)->GetStringCritical(env, aString, NULL); + (*env)->ReleaseStringCritical(env, aString, str_pointer); + + } else if (strncmp(safe_arg, CALL, strlen(CALL)) == 0) { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + char* type = NULL; + char* modifier = NULL; + char* method_sig = malloc(MAX_ARG_LEN); + char* method_name = malloc(MAX_ARG_LEN); + if ((method_sig == NULL) || (method_name == NULL)) { + goto cannot_call; + } + int rval = get_type_and_modifier(safe_arg+4, &type, &modifier); + if (rval == -1) { + goto cannot_call; + } + int arg_len = strlen(safe_arg); + jclass testClass = (*env)->FindClass(env, TEST_CLASS); + if (testClass == NULL) { + /* Bail out, cannot find class. */ + goto cannot_call; + } + if ((modifier != NULL) && (strncmp(modifier, STATIC, + strlen(STATIC)) == 0)) { + snprintf(method_name, MAX_ARG_LEN, "get%s%s", modifier, type); + if (strncmp(type, BOOLEAN, strlen(type)) == 0) { + strncpy(method_sig, "()Z", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_boolean_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticBooleanMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticBooleanMethod(env, testClass, method); + } + } else if (strncmp(type, BYTE, strlen(type)) == 0) { + strncpy(method_sig, "()B", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_byte_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticByteMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticByteMethod(env, testClass, method); + } + } else if (strncmp(type, CHAR, strlen(type)) == 0) { + strncpy(method_sig, "()C", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_char_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticCharMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticCharMethod(env, testClass, method); + } + } else if (strncmp(type, DOUBLE, strlen(type)) == 0) { + strncpy(method_sig, "()D", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_double_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticDoubleMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticDoubleMethod(env, testClass, method); + } + } else if (strncmp(type, FLOAT, strlen(type)) == 0) { + strncpy(method_sig, "()F", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_float_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticFloatMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticFloatMethod(env, testClass, method); + } + } else if (strncmp(type, INT, strlen(type)) == 0) { + strncpy(method_sig, "()I", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_int_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticIntMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticIntMethod(env, testClass, method); + } + } else if (strncmp(type, LONG, strlen(type)) == 0) { + strncpy(method_sig, "()J", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_long_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticLongMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticLongMethod(env, testClass, method); + } + } else if (strncmp(type, OBJECT, strlen(type)) == 0) { + strncpy(method_sig, "()Ljava/lang/Object;", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_object_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticObjectMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticObjectMethod(env, testClass, method); + } + } else if (strncmp(type, SHORT, strlen(type)) == 0) { + strncpy(method_sig, "()S", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_short_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticShortMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticShortMethod(env, testClass, method); + } + } else if (strncmp(type, VOID, strlen(type)) == 0) { + strncpy(method_sig, "()V", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetStaticMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + static_void_v_wrap(&env, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallStaticVoidMethodA(env, testClass, method, NULL); + } else { + (*env)->CallStaticVoidMethod(env, testClass, method); + } + } else { + /* Type not recognized. */ + goto cannot_call; + } + } else { + jmethodID constructor = (*env)->GetMethodID(env, testClass, + "<init>", "()V"); + if (constructor == NULL) { + /* Bail out, cannot find constructor. */ + goto cannot_call; + } + jobject testInstance = (*env)->NewObject(env, testClass, constructor); + if (testInstance == NULL) { + /* Bail out, cannot create object. */ + goto cannot_call; + } + snprintf(method_name, MAX_ARG_LEN, "get%s", type); + if ((modifier != NULL) && (strncmp(modifier, NONVIRTUAL, + strlen(NONVIRTUAL)) == 0)) { + if (strncmp(type, BOOLEAN, strlen(type)) == 0) { + strncpy(method_sig, "()Z", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_boolean_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualBooleanMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualBooleanMethod(env, testInstance, testClass, + method); + } + } else if (strncmp(type, BYTE, strlen(type)) == 0) { + strncpy(method_sig, "()B", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_byte_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualByteMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualByteMethod(env, testInstance, testClass, + method); + } + } else if (strncmp(type, CHAR, strlen(type)) == 0) { + strncpy(method_sig, "()C", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_char_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualCharMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualCharMethod(env, testInstance, testClass, + method); + } + } else if (strncmp(type, DOUBLE, strlen(type)) == 0) { + strncpy(method_sig, "()D", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_double_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualDoubleMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualDoubleMethod(env, testInstance, testClass, + method); + } + } else if (strncmp(type, FLOAT, strlen(type)) == 0) { + strncpy(method_sig, "()F", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_float_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualFloatMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualFloatMethod(env, testInstance, testClass, + method); + } + } else if (strncmp(type, INT, strlen(type)) == 0) { + strncpy(method_sig, "()I", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_int_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualIntMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualIntMethod(env, testInstance, testClass, + method); + } + } else if (strncmp(type, LONG, strlen(type)) == 0) { + strncpy(method_sig, "()J", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_long_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualLongMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualLongMethod(env, testInstance, testClass, + method); + } + } else if (strncmp(type, OBJECT, strlen(type)) == 0) { + strncpy(method_sig, "()Ljava/lang/Object;", 21); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_object_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualObjectMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualObjectMethod(env, testInstance, testClass, + method); + } + } else if (strncmp(type, SHORT, strlen(type)) == 0) { + strncpy(method_sig, "()S", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_short_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualShortMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualShortMethod(env, testInstance, testClass, + method); + } + } else if (strncmp(type, VOID, strlen(type)) == 0) { + strncpy(method_sig, "()V", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + nonvirtual_void_v_wrap(&env, &testInstance, &testClass, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallNonvirtualVoidMethodA(env, testInstance, testClass, + method, NULL); + } else { + (*env)->CallNonvirtualVoidMethod(env, testInstance, testClass, + method); + } + } else { + /* Type not recognized. */ + goto cannot_call; + } + } else { + if (strncmp(type, BOOLEAN, strlen(type)) == 0) { + strncpy(method_sig, "()Z", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + boolean_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallBooleanMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallBooleanMethod(env, testInstance, method); + } + } else if (strncmp(type, BYTE, strlen(type)) == 0) { + strncpy(method_sig, "()B", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + byte_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallByteMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallByteMethod(env, testInstance, method); + } + } else if (strncmp(type, CHAR, strlen(type)) == 0) { + strncpy(method_sig, "()C", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + char_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallCharMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallCharMethod(env, testInstance, method); + } + } else if (strncmp(type, DOUBLE, strlen(type)) == 0) { + strncpy(method_sig, "()D", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + double_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallDoubleMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallDoubleMethod(env, testInstance, method); + } + } else if (strncmp(type, FLOAT, strlen(type)) == 0) { + strncpy(method_sig, "()F", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + float_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallFloatMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallFloatMethod(env, testInstance, method); + } + } else if (strncmp(type, INT, strlen(type)) == 0) { + strncpy(method_sig, "()I", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + int_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallIntMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallIntMethod(env, testInstance, method); + } + } else if (strncmp(type, LONG, strlen(type)) == 0) { + strncpy(method_sig, "()J", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + long_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallLongMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallLongMethod(env, testInstance, method); + } + } else if (strncmp(type, OBJECT, strlen(type)) == 0) { + strncpy(method_sig, "()Ljava/lang/Object;", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + object_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallObjectMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallObjectMethod(env, testInstance, method); + } + } else if (strncmp(type, SHORT, strlen(type)) == 0) { + strncpy(method_sig, "()S", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + short_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallShortMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallShortMethod(env, testInstance, method); + } + } else if (strncmp(type, VOID, strlen(type)) == 0) { + strncpy(method_sig, "()V", MAX_ARG_LEN-1); + jmethodID method = (*env)->GetMethodID(env, testClass, + method_name, method_sig); + if (method == NULL) { + /* Bail out, cannot find method. */ + goto cannot_call; + } + if (safe_arg[arg_len - 1] == 'V') { + void_v_wrap(&env, &testInstance, &method); + } else if (safe_arg[arg_len - 1] == 'A') { + (*env)->CallVoidMethodA(env, testInstance, method, NULL); + } else { + (*env)->CallVoidMethod(env, testInstance, method); + } + } else { + /* Type not recognized. */ + goto cannot_call; + } + } + } +cannot_call: + if (type != NULL) { + free(type); + type = NULL; + } + if (modifier != NULL) { + free(modifier); + modifier = NULL; + } + if (method_sig != NULL) { + free(method_sig); + method_sig = NULL; + } + if (method_name != NULL) { + free(method_name); + method_name = NULL; + } + } else if ((strncmp(safe_arg, GET, strlen(GET)) == 0) || + (strncmp(safe_arg, NEW, strlen(NEW)) == 0) || + (strncmp(safe_arg, SET, strlen(SET)) == 0) || + (strncmp(safe_arg, RELEASE, strlen(RELEASE)) == 0)) { + char* type; + char* modifier; + char* field_name = malloc(MAX_ARG_LEN); + char* field_sig = malloc(MAX_ARG_LEN); + if ((field_name == NULL) || (field_sig == NULL)) { + goto done_or_error; + } + int rval; + if (strncmp(safe_arg, RELEASE, strlen(RELEASE)) == 0) { + rval = get_type_and_modifier(safe_arg+7, &type, &modifier); + } else { + rval = get_type_and_modifier(safe_arg+3, &type, &modifier); + } + if (rval == -1) { + goto done_or_error; + } + jboolean check_static = JNI_FALSE; + jboolean check_boolean = JNI_FALSE; + jboolean check_byte = JNI_FALSE; + jboolean check_char = JNI_FALSE; + jboolean check_double = JNI_FALSE; + jboolean check_float = JNI_FALSE; + jboolean check_int = JNI_FALSE; + jboolean check_long = JNI_FALSE; + jboolean check_object = JNI_FALSE; + jboolean check_short = JNI_FALSE; + jboolean check_field = is_field_op(safe_arg); + jboolean check_array = is_array_op(safe_arg); + if (strncmp(type, BOOLEAN, strlen(type)) == 0) { + check_boolean = JNI_TRUE; + snprintf(field_sig, MAX_ARG_LEN-1, "Z"); + } else if (strncmp(type, BYTE, strlen(type)) == 0) { + check_byte = JNI_TRUE; + snprintf(field_sig, MAX_ARG_LEN-1, "B"); + } else if (strncmp(type, CHAR, strlen(type)) == 0) { + check_char = JNI_TRUE; + snprintf(field_sig, MAX_ARG_LEN-1, "C"); + } else if (strncmp(type, DOUBLE, strlen(type)) == 0) { + check_double = JNI_TRUE; + snprintf(field_sig, MAX_ARG_LEN-1, "D"); + } else if (strncmp(type, FLOAT, strlen(type)) == 0) { + check_float = JNI_TRUE; + snprintf(field_sig, MAX_ARG_LEN-1, "F"); + } else if (strncmp(type, INT, strlen(type)) == 0) { + check_int = JNI_TRUE; + snprintf(field_sig, MAX_ARG_LEN-1, "I"); + } else if (strncmp(type, LONG, strlen(type)) == 0) { + check_long = JNI_TRUE; + snprintf(field_sig, MAX_ARG_LEN-1, "J"); + } else if (strncmp(type, OBJECT, strlen(type)) == 0) { + check_object = JNI_TRUE; + snprintf(field_sig, MAX_ARG_LEN-1, "Ljava/lang/String;"); + } else if (strncmp(type, SHORT, strlen(type)) == 0) { + check_short = JNI_TRUE; + snprintf(field_sig, MAX_ARG_LEN-1, "S"); + } else { + goto done_or_error; + } + if (modifier == NULL) { + snprintf(field_name, MAX_ARG_LEN-1, "my%s", type); + } else { + if (strncmp(modifier, STATIC, strlen(modifier)) == 0) { + check_static = JNI_TRUE; + snprintf(field_name, MAX_ARG_LEN-1, "my%s%s", modifier, type); + } else { + goto done_or_error; + } + } + if ((check_static == JNI_FALSE) && + (strncmp(safe_arg, GET, strlen(GET)) == 0)) { + /* Get<PrimitiveType>Field() functions are optimized by default, + * bypassing the probe locations. + */ + JavaVMOption options[1]; + options[0].optionString = "-XX:-UseFastJNIAccessors"; + JavaVMInitArgs vm_args; + vm_args.version = JNI_VERSION_1_6; + vm_args.nOptions = 1; + vm_args.options = options; + jint created = create_java_vm_wrap(&vm_args); + if (created != 0) { + exit(-1); + } + } else { + jint created = create_java_vm_wrap(NULL); + if (created != 0) { + exit(-1); + } + } + if (check_field == JNI_TRUE) { + /* Field */ + jclass testClass = (*env)->FindClass(env, TEST_CLASS); + if (testClass == NULL) { + /* Bail out, cannot find class. */ + goto done_or_error; + } + jobject testInstance = NULL; + jfieldID theFieldID = NULL; + if (check_static == JNI_TRUE) { + theFieldID = (*env)->GetStaticFieldID(env, testClass, field_name, + field_sig); + } else { + jmethodID constructor = (*env)->GetMethodID(env, testClass, + "<init>", "()V"); + if (constructor == NULL) { + /* Bail out, cannot find constructor. */ + goto done_or_error; + } + testInstance = (*env)->NewObject(env, testClass, constructor); + if (testInstance == NULL) { + /* Bail out, cannot create object. */ + goto done_or_error; + } + theFieldID = (*env)->GetFieldID(env, testClass, field_name, field_sig); + } + if (theFieldID == NULL) { + /* Bail out, cannot access field. */ + goto done_or_error; + } + if (check_boolean == JNI_TRUE) { + if (strncmp(safe_arg, GET, strlen(GET)) == 0) { + if (check_static == JNI_TRUE) { + jboolean aBool = (*env)->GetStaticBooleanField(env, testClass, + theFieldID); + } else { + jboolean aBool = (*env)->GetBooleanField(env, testInstance, + theFieldID); + } + } else if (strncmp(safe_arg, SET, strlen(SET)) == 0) { + jboolean aBool = JNI_TRUE; + if (check_static == JNI_TRUE) { + (*env)->SetStaticBooleanField(env, testClass, theFieldID, aBool); + } else { + (*env)->SetBooleanField(env, testInstance, theFieldID, aBool); + } + } + } else if (check_byte == JNI_TRUE) { + if (strncmp(safe_arg, GET, strlen(GET)) == 0) { + if (check_static == JNI_TRUE) { + jbyte aByte = (*env)->GetStaticByteField(env, testClass, + theFieldID); + } else { + jbyte aByte = (*env)->GetByteField(env, testInstance, theFieldID); + } + } else if (strncmp(safe_arg, SET, strlen(SET)) == 0) { + jbyte aByte = (jbyte) 2; + if (check_static == JNI_TRUE) { + (*env)->SetStaticByteField(env, testClass, theFieldID, aByte); + } else { + (*env)->SetByteField(env, testInstance, theFieldID, aByte); + } + } + } else if (check_char == JNI_TRUE) { + if (strncmp(safe_arg, GET, strlen(GET)) == 0) { + if (check_static == JNI_TRUE) { + jchar aChar = (*env)->GetStaticCharField(env, testClass, + theFieldID); + } else { + jchar aChar = (*env)->GetCharField(env, testInstance, theFieldID); + } + } else if (strncmp(safe_arg, SET, strlen(SET)) == 0) { + jchar aChar = 'A'; + if (check_static == JNI_TRUE) { + (*env)->SetStaticCharField(env, testClass, theFieldID, aChar); + } else { + (*env)->SetCharField(env, testInstance, theFieldID, aChar); + } + } + } else if (check_double == JNI_TRUE) { + if (strncmp(safe_arg, GET, strlen(GET)) == 0) { + if (check_static == JNI_TRUE) { + jdouble aDouble = (*env)->GetStaticDoubleField(env, testClass, + theFieldID); + } else { + jdouble aDouble = (*env)->GetDoubleField(env, testInstance, + theFieldID); + } + } else if (strncmp(safe_arg, SET, strlen(SET)) == 0) { + jdouble aDouble = (jdouble) 2.5; + if (check_static == JNI_TRUE) { + (*env)->SetStaticDoubleField(env, testClass, theFieldID, aDouble); + } else { + (*env)->SetDoubleField(env, testInstance, theFieldID, aDouble); + } + } + } else if (check_float == JNI_TRUE) { + if (strncmp(safe_arg, GET, strlen(GET)) == 0) { + if (check_static == JNI_TRUE) { + jfloat aFloat = (*env)->GetStaticFloatField(env, testClass, + theFieldID); + } else { + jfloat aFloat = (*env)->GetFloatField(env, testInstance, + theFieldID); + } + } else if (strncmp(safe_arg, SET, strlen(SET)) == 0) { + jfloat aFloat = (jfloat) 3.5; + if (check_static == JNI_TRUE) { + (*env)->SetStaticFloatField(env, testClass, theFieldID, aFloat); + } else { + (*env)->SetFloatField(env, testInstance, theFieldID, aFloat); + } + } + } else if (check_int == JNI_TRUE) { + if (strncmp(safe_arg, GET, strlen(GET)) == 0) { + if (check_static == JNI_TRUE) { + jint aInt = (*env)->GetStaticIntField(env, testClass, theFieldID); + } else { + jint aInt = (*env)->GetIntField(env, testInstance, theFieldID); + } + } else if (strncmp(safe_arg, SET, strlen(SET)) == 0) { + jint aInt = (jint) 7; + if (check_static == JNI_TRUE) { + (*env)->SetStaticIntField(env, testClass, theFieldID, aInt); + } else { + (*env)->SetIntField(env, testInstance, theFieldID, aInt); + } + } + } else if (check_long == JNI_TRUE) { + if (strncmp(safe_arg, GET, strlen(GET)) == 0) { + if (check_static == JNI_TRUE) { + jlong aLong = (*env)->GetStaticLongField(env, testClass, + theFieldID); + } else { + jlong aLong = (*env)->GetLongField(env, testInstance, theFieldID); + } + } else if (strncmp(safe_arg, SET, strlen(SET)) == 0) { + jlong aLong = (jlong) 13; + if (check_static == JNI_TRUE) { + (*env)->SetStaticLongField(env, testClass, theFieldID, aLong); + } else { + (*env)->SetLongField(env, testInstance, theFieldID, aLong); + } + } + } else if (check_object == JNI_TRUE) { + if (strncmp(safe_arg, GET, strlen(GET)) == 0) { + if (check_static == JNI_TRUE) { + jobject aObject = (*env)->GetStaticObjectField(env, testClass, + theFieldID); + } else { + jobject aObject = (*env)->GetObjectField(env, testInstance, + theFieldID); + } + } else if (strncmp(safe_arg, SET, strlen(SET)) == 0) { + jchar string_chars[4] = + { (jchar) 0x57, (jchar) 0x4F, (jchar) 0x52, (jchar) 0x44 }; + jobject aObject = (jobject) (*env)->NewString(env, string_chars, + (jsize) 4); + if (aObject == NULL) { + goto done_or_error; + } + if (check_static == JNI_TRUE) { + (*env)->SetStaticObjectField(env, testClass, theFieldID, aObject); + } else { + (*env)->SetObjectField(env, testInstance, theFieldID, aObject); + } + } + } else if (check_short == JNI_TRUE) { + if (strncmp(safe_arg, GET, strlen(GET)) == 0) { + if (check_static == JNI_TRUE) { + jshort aShort = (*env)->GetStaticShortField(env, testClass, + theFieldID); + } else { + jshort aShort = (*env)->GetShortField(env, testInstance, + theFieldID); + } + } else if (strncmp(safe_arg, SET, strlen(SET)) == 0) { + jshort aShort = (jshort) 11; + if (check_static == JNI_TRUE) { + (*env)->SetStaticShortField(env, testClass, theFieldID, aShort); + } else { + (*env)->SetShortField(env, testInstance, theFieldID, aShort); + } + } + } + } else if (check_array == JNI_TRUE) { + /* Array */ + if (check_boolean == JNI_TRUE) { + jbooleanArray jboolean_array = (*env)->NewBooleanArray(env, + TEST_ARRAY_LEN); + if (jboolean_array == NULL) { + goto done_or_error; + } + jboolean boolean_array[TEST_ARRAY_LEN] = { JNI_TRUE, JNI_TRUE, JNI_TRUE, + JNI_TRUE, JNI_TRUE }; + (*env)->SetBooleanArrayRegion(env, jboolean_array, 0, TEST_ARRAY_LEN, + boolean_array); + jboolean* boolean_buf = malloc(sizeof(jboolean) * TEST_ARRAY_LEN); + if (boolean_buf == NULL) { + goto done_or_error; + } + (*env)->GetBooleanArrayRegion(env, jboolean_array, 0, TEST_ARRAY_LEN, + boolean_buf); + jboolean* jbool_p = (*env)->GetBooleanArrayElements(env, + jboolean_array, NULL); + if (jbool_p == NULL) { + goto done_or_error; + } + (*env)->ReleaseBooleanArrayElements(env, jboolean_array, jbool_p, + JNI_ABORT); + } else if (check_byte == JNI_TRUE) { + jbyteArray jbyte_array = (*env)->NewByteArray(env, TEST_ARRAY_LEN); + if (jbyte_array == NULL) { + goto done_or_error; + } + jbyte byte_array[TEST_ARRAY_LEN] = { 0, 0, 0, 0, 0 }; + (*env)->SetByteArrayRegion(env, jbyte_array, 0, TEST_ARRAY_LEN, + byte_array); + jbyte* byte_buf = malloc(sizeof(jbyte) * TEST_ARRAY_LEN); + if (byte_buf == NULL) { + goto done_or_error; + } + (*env)->GetByteArrayRegion(env, jbyte_array, 0, TEST_ARRAY_LEN, + byte_buf); + jbyte* jbyte_p = (*env)->GetByteArrayElements(env, + jbyte_array, NULL); + if (jbyte_p == NULL) { + goto done_or_error; + } + (*env)->ReleaseByteArrayElements(env, jbyte_array, jbyte_p, JNI_ABORT); + } else if (check_char == JNI_TRUE) { + jcharArray jchar_array = (*env)->NewCharArray(env, TEST_ARRAY_LEN); + if (jchar_array == NULL) { + goto done_or_error; + } + jchar char_array[TEST_ARRAY_LEN] = { (jchar) 'a', (jchar) 'b', + (jchar) 'c', (jchar) 'd', (jchar) 'e' }; + (*env)->SetCharArrayRegion(env, jchar_array, 0, TEST_ARRAY_LEN, + char_array); + jchar* char_buf = malloc(sizeof(jchar) * TEST_ARRAY_LEN); + if (char_buf == NULL) { + goto done_or_error; + } + (*env)->GetCharArrayRegion(env, jchar_array, 0, TEST_ARRAY_LEN, + char_buf); + jchar* jchar_p = (*env)->GetCharArrayElements(env, jchar_array, NULL); + if (jchar_p == NULL) { + goto done_or_error; + } + (*env)->ReleaseCharArrayElements(env, jchar_array, jchar_p, JNI_ABORT); + } else if (check_double == JNI_TRUE) { + jdoubleArray jdouble_array = (*env)->NewDoubleArray(env, TEST_ARRAY_LEN); + if (jdouble_array == NULL) { + goto done_or_error; + } + jdouble double_array[TEST_ARRAY_LEN] = { (jdouble) 1, (jdouble) 2, + (jdouble) 3, (jdouble) 4, (jdouble) 5 }; + (*env)->SetDoubleArrayRegion(env, jdouble_array, 0, TEST_ARRAY_LEN, + double_array); + jdouble* double_buf = malloc(sizeof(jdouble) * TEST_ARRAY_LEN); + if (double_buf == NULL) { + goto done_or_error; + } + (*env)->GetDoubleArrayRegion(env, jdouble_array, 0, TEST_ARRAY_LEN, + double_buf); + jdouble* jdouble_p = (*env)->GetDoubleArrayElements(env, + jdouble_array, NULL); + if (jdouble_p == NULL) { + goto done_or_error; + } + (*env)->ReleaseDoubleArrayElements(env, jdouble_array, jdouble_p, + JNI_ABORT); + } else if (check_float == JNI_TRUE) { + jfloatArray jfloat_array = (*env)->NewFloatArray(env, TEST_ARRAY_LEN); + if (jfloat_array == NULL) { + goto done_or_error; + } + jfloat float_array[TEST_ARRAY_LEN] = { (jfloat) 2.5, (jfloat) 6.7, + (jfloat) 11.2, (jfloat) 4.8, (jfloat) 8.4 }; + (*env)->SetFloatArrayRegion(env, jfloat_array, 0, TEST_ARRAY_LEN, + float_array); + jfloat* float_buf = malloc(sizeof(jfloat) * TEST_ARRAY_LEN); + if (float_buf == NULL) { + goto done_or_error; + } + (*env)->GetFloatArrayRegion(env, jfloat_array, 0, TEST_ARRAY_LEN, + float_buf); + jfloat* jfloat_p = (*env)->GetFloatArrayElements(env, jfloat_array, + NULL); + if (jfloat_p == NULL) { + goto done_or_error; + } + (*env)->ReleaseFloatArrayElements(env, jfloat_array, jfloat_p, + JNI_ABORT); + } else if (check_int == JNI_TRUE) { + jintArray jint_array = (*env)->NewIntArray(env, TEST_ARRAY_LEN); + if (jint_array == NULL) { + goto done_or_error; + } + jint int_array[TEST_ARRAY_LEN] = { (jint) 1, (jint) 2, (jint) 3, + (jint) 4, (jint) 5 }; + (*env)->SetIntArrayRegion(env, jint_array, 0, TEST_ARRAY_LEN, + int_array); + jint* int_buf = malloc(sizeof(jint) * TEST_ARRAY_LEN); + if (int_buf == NULL) { + goto done_or_error; + } + (*env)->GetIntArrayRegion(env, jint_array, 0, TEST_ARRAY_LEN, int_buf); + jint* jint_p = (*env)->GetIntArrayElements(env, jint_array, NULL); + if (jint_p == NULL) { + goto done_or_error; + } + (*env)->ReleaseIntArrayElements(env, jint_array, jint_p, JNI_ABORT); + } else if (check_long == JNI_TRUE) { + jlongArray jlong_array = (*env)->NewLongArray(env, TEST_ARRAY_LEN); + if (jlong_array == NULL) { + goto done_or_error; + } + jlong long_array[TEST_ARRAY_LEN] = { (jlong) 1, (jlong) 2, (jlong) 3, + (jlong) 4, (jlong) 5 }; + (*env)->SetLongArrayRegion(env, jlong_array, 0, TEST_ARRAY_LEN, + long_array); + jlong* long_buf = malloc(sizeof(jlong) * TEST_ARRAY_LEN); + if (long_buf == NULL) { + goto done_or_error; + } + (*env)->GetLongArrayRegion(env, jlong_array, 0, TEST_ARRAY_LEN, + long_buf); + jlong* jlong_p = (*env)->GetLongArrayElements(env, jlong_array, NULL); + if (jlong_p == NULL) { + goto done_or_error; + } + (*env)->ReleaseLongArrayElements(env, jlong_array, jlong_p, JNI_ABORT); + } else if (check_object == JNI_TRUE) { + jchar string_chars[4] = + { (jchar) 0x57, (jchar) 0x4F, (jchar) 0x52, (jchar) 0x44 }; + jstring aString = (*env)->NewString(env, string_chars, (jsize) 4); + if (aString == NULL) { + goto done_or_error; + } + jclass stringClass = (*env)->GetObjectClass(env, (jobject) aString); + if (stringClass == NULL) { + goto done_or_error; + } + jobjectArray oArray = (*env)->NewObjectArray(env, 5, stringClass, NULL); + if (oArray == NULL) { + goto done_or_error; + } + (*env)->SetObjectArrayElement(env, oArray, 1, (jobject) aString); + if ((*env)->ExceptionCheck(env) == JNI_TRUE) { + goto done_or_error; + } + jobject bString = (*env)->GetObjectArrayElement(env, oArray, 1); + } else if (check_short == JNI_TRUE) { + jshortArray jshort_array = (*env)->NewShortArray(env, TEST_ARRAY_LEN); + if (jshort_array == NULL) { + goto done_or_error; + } + jshort short_array[TEST_ARRAY_LEN] = { (jshort) 1, (jshort) 2, + (jshort) 3, (jshort) 4, (jshort) 5 }; + (*env)->SetShortArrayRegion(env, jshort_array, 0, TEST_ARRAY_LEN, + short_array); + jshort* short_buf = malloc(sizeof(jshort) * TEST_ARRAY_LEN); + if (short_buf == NULL) { + goto done_or_error; + } + (*env)->GetShortArrayRegion(env, jshort_array, 0, TEST_ARRAY_LEN, + short_buf); + jshort* jshort_p = (*env)->GetShortArrayElements(env, jshort_array, + NULL); + if (jshort_p == NULL) { + goto done_or_error; + } + (*env)->ReleaseShortArrayElements(env, jshort_array, jshort_p, + JNI_ABORT); + } + } +done_or_error: + if (type != NULL) { + free(type); + type = NULL; + } + if (modifier != NULL) { + free(modifier); + modifier = NULL; + } + if (field_name != NULL) { + free(field_name); + field_name = NULL; + } + if (field_sig != NULL) { + free(field_sig); + field_sig = NULL; + } + } else { +/* bad_usage("Probe specified not found.");*/ + exit(-1); + } + +/* Goto labels are ugly, but we use one anyways to provide a way to + * jump out of a series of JNI operations if an unsafe operation is reached, + * while still ensuring the JVM gets shut down. + */ +end_vm: + if (safe_arg != NULL) { + free(safe_arg); + safe_arg = NULL; + } + (*jvm)->DestroyJavaVM(jvm); +} + +void bad_usage(char* error_msg) { + fprintf(stderr, "Error: %s\nThis program requires a single argument.\nThe argument should specify a probe alias in the hotspot_jni tapset.\nThese probes aliases are of the form \"hotspot.jni.<name>\".\nThe argument should consist of the <name>.\n", error_msg); +} + +void* run_attach_current_thread(void* style) { + jint r_val; + JavaVM* javavm = NULL; + jsize returned_count = 0; + r_val = JNI_GetCreatedJavaVMs(&javavm, (jsize) 1, &returned_count); + if ((r_val != JNI_OK) || (returned_count < 1)) { + pthread_exit(NULL); + } + struct JavaVMAttachArgs attach_args; + attach_args.version = (jint) JNI_VERSION_1_6; + attach_args.name = "Attached Thread"; + attach_args.group = (jobject) NULL; + JNIEnv *attach_env; + if (*(int*)style == (int) DAEMON) { + r_val = (*javavm)->AttachCurrentThreadAsDaemon(javavm, + (void **) &attach_env, (void *) &attach_args); + } else if (*(int*)style == (int) NOT_DAEMON) { + r_val = (*javavm)->AttachCurrentThread(javavm, + (void **) &attach_env, (void *) &attach_args); + } else { + pthread_exit(NULL); + } + if (r_val != JNI_OK) { + pthread_exit(NULL); + } + (*javavm)->DetachCurrentThread(javavm); + pthread_exit(NULL); +} + +int get_type_and_modifier(char* arg, char** type_p, char** mod_p) { + char* type = arg; + if (strncmp(type, STATIC, strlen(STATIC)) == 0) { + *mod_p = malloc(strlen(STATIC) + 1); + if (*mod_p == NULL) { + *type_p = NULL; + return -1; + } + strncpy(*mod_p, type, strlen(STATIC)); + type += strlen(STATIC); + } else if (strncmp(type, NONVIRTUAL, strlen(NONVIRTUAL)) == 0) { + *mod_p = malloc(strlen(NONVIRTUAL) + 1); + if (*mod_p == NULL) { + *type_p = NULL; + return -1; + } + strncpy(*mod_p, type, strlen(NONVIRTUAL)); + type += strlen(NONVIRTUAL); + } else { + *mod_p = NULL; + } + char* char_after_type = strchr(type, (int) 'M'); + /* 'M' targets "Method" in argument. */ + if (char_after_type == NULL) { + char_after_type = strchr(type, (int) 'A'); + /* 'A' targets "Array<Elements|Region>" in argument. */ + if (char_after_type == NULL) { + /* 'F' targets "Field" in argument. */ + char_after_type = strrchr(type, (int) 'F'); + } + } + int type_len = char_after_type - type; + if (type_len <= 0) { + /* char_after_type doesn't point at 'M', 'A', or 'F', or the special case + * where it points at the 'F' in "Float". */ + *type_p = NULL; + return -1; + } + *type_p = malloc(type_len + 1); + if (*type_p == NULL) { + return -1; + } + strncpy(*type_p, type, (size_t) type_len); + return 0; +} + +jboolean is_field_op(char* arg) { + char* poss_field = strrchr(arg, (int) 'F'); + if (poss_field != NULL) { + if (strncmp(poss_field, FIELD, strlen(FIELD)) == 0) { + return JNI_TRUE; + } + } + return JNI_FALSE; +} + +jboolean is_array_op(char* arg) { + char* poss_array = strrchr(arg, (int) 'A'); + if (poss_array != NULL) { + if (strncmp(poss_array, ARRAY, strlen(ARRAY)) == 0) { + return JNI_TRUE; + } + } + return JNI_FALSE; +} + +jint create_java_vm_wrap(JavaVMInitArgs* args) { + JavaVMInitArgs def_vm_args; + JavaVMInitArgs* vm_args_p; + if (args == NULL) { + def_vm_args.version = JNI_VERSION_1_6; + def_vm_args.nOptions = 0; + def_vm_args.options = NULL; + vm_args_p = &def_vm_args; + } else { + vm_args_p = args; + } + + return JNI_CreateJavaVM(&jvm, (void **) &env, vm_args_p); +} + +jobject new_object_v_wrap(JNIEnv* env_, jclass* class_p, + jmethodID* construct, ...) { + va_list var_args; + va_start(var_args, construct); + jobject instance = (*env_)->NewObjectV(env_, *class_p, *construct, var_args); + va_end(var_args); + return instance; +} + +jboolean boolean_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jboolean to_return = (**env_p)->CallBooleanMethodV(*env_p, *obj_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jbyte byte_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jbyte to_return = (**env_p)->CallByteMethodV(*env_p, *obj_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jchar char_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jchar to_return = (**env_p)->CallCharMethodV(*env_p, *obj_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jdouble double_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jdouble to_return = (**env_p)->CallDoubleMethodV(*env_p, *obj_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jfloat float_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jfloat to_return = (**env_p)->CallFloatMethodV(*env_p, *obj_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jint int_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jint to_return = (**env_p)->CallIntMethodV(*env_p, *obj_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jlong long_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jlong to_return = (**env_p)->CallLongMethodV(*env_p, *obj_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jobject object_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jobject to_return = (**env_p)->CallObjectMethodV(*env_p, *obj_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jshort short_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jshort to_return = (**env_p)->CallShortMethodV(*env_p, *obj_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +void void_v_wrap(JNIEnv** env_p, jobject* obj_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + (**env_p)->CallVoidMethodV(*env_p, *obj_p, *method_p, var_args); + va_end(var_args); + return; +} + +jboolean nonvirtual_boolean_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jboolean to_return = (**env_p)->CallNonvirtualBooleanMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return to_return; +} +jbyte nonvirtual_byte_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jbyte to_return = (**env_p)->CallNonvirtualByteMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return to_return; +} +jchar nonvirtual_char_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jchar to_return = (**env_p)->CallNonvirtualCharMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return to_return; +} +jdouble nonvirtual_double_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jdouble to_return = (**env_p)->CallNonvirtualDoubleMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return to_return; +} +jfloat nonvirtual_float_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jfloat to_return = (**env_p)->CallNonvirtualFloatMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return to_return; +} +jint nonvirtual_int_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jint to_return = (**env_p)->CallNonvirtualIntMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return to_return; +} +jlong nonvirtual_long_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jlong to_return = (**env_p)->CallNonvirtualLongMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return to_return; +} +jobject nonvirtual_object_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jobject to_return = (**env_p)->CallNonvirtualObjectMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return to_return; +} +jshort nonvirtual_short_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jshort to_return = (**env_p)->CallNonvirtualShortMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return to_return; +} +void nonvirtual_void_v_wrap(JNIEnv** env_p, jobject* obj_p, + jclass* jclass_p, jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + (**env_p)->CallNonvirtualVoidMethodV(*env_p, *obj_p, + *jclass_p, *method_p, var_args); + va_end(var_args); + return; +} + +jboolean static_boolean_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jboolean to_return = (**env_p)->CallStaticBooleanMethodV(*env_p, *jclass_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jbyte static_byte_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jbyte to_return = (**env_p)->CallStaticByteMethodV(*env_p, *jclass_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jchar static_char_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jchar to_return = (**env_p)->CallStaticCharMethodV(*env_p, *jclass_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jdouble static_double_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jdouble to_return = (**env_p)->CallStaticDoubleMethodV(*env_p, *jclass_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jfloat static_float_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jfloat to_return = (**env_p)->CallStaticFloatMethodV(*env_p, *jclass_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jint static_int_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jint to_return = (**env_p)->CallStaticIntMethodV(*env_p, *jclass_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jlong static_long_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jlong to_return = (**env_p)->CallStaticLongMethodV(*env_p, *jclass_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jobject static_object_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jobject to_return = (**env_p)->CallStaticObjectMethodV(*env_p, *jclass_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +jshort static_short_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + jshort to_return = (**env_p)->CallStaticShortMethodV(*env_p, *jclass_p, + *method_p, var_args); + va_end(var_args); + return to_return; +} +void static_void_v_wrap(JNIEnv** env_p, jclass* jclass_p, + jmethodID* method_p, ...) { + va_list var_args; + va_start(var_args, method_p); + (**env_p)->CallStaticVoidMethodV(*env_p, *jclass_p, *method_p, var_args); + va_end(var_args); + return; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/JNITestClass.c Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,7 @@ +#include "jni.h" +#include "JNITestClass.h" + +JNIEXPORT void JNICALL Java_JNITestClass_doNothing + (JNIEnv * env, jobject this) { + return; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/JNITestClass.h Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include "jni.h" +/* Header for class JNITestClass */ + +#ifndef _Included_JNITestClass +#define _Included_JNITestClass +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: JNITestClass + * Method: doNothing + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_JNITestClass_doNothing + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/JNITestClass.java Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,121 @@ +package staptest; + +public class JNITestClass { + public boolean myBoolean; + public byte myByte; + public char myChar; + public double myDouble; + public float myFloat; + public int myInt; + public long myLong; + public String myObject; + public short myShort; + + public static boolean myStaticBoolean = false; + public static byte myStaticByte = 1; + public static char myStaticChar = 'b'; + public static double myStaticDouble = 5.5; + public static float myStaticFloat = (float) 2.75; + public static int myStaticInt = 32; + public static long myStaticLong = 64; + public static String myStaticObject = "aString"; + public static short myStaticShort = 16; + + public JNITestClass() { + myBoolean = true; + myByte = 0; + myChar = 'a'; + myDouble = 1.5; + myFloat = (float) 0.75; + myInt = 4; + myLong = 8; + myObject = "myString"; + myShort = 2; + } + + private native void doNothing(); + + public boolean getBoolean() { + return myBoolean; + } + + public byte getByte() { + return myByte; + } + + public char getChar() { + return myChar; + } + + public double getDouble() { + return myDouble; + } + + public float getFloat() { + return myFloat; + } + + public int getInt() { + return myInt; + } + + public long getLong() { + return myLong; + } + + public Object getObject() { + return (Object) new String(myObject); + } + + public short getShort() { + return myShort; + } + + /* Ridiculous name and useless method, but this removes needing a + * special case for testing CallVoidMethod[A|V] probes. */ + public void getVoid() { + return; + } + + public static boolean getStaticBoolean() { + return myStaticBoolean; + } + + public static byte getStaticByte() { + return myStaticByte; + } + + public static char getStaticChar() { + return myStaticChar; + } + + public static double getStaticDouble() { + return myStaticDouble; + } + + public static float getStaticFloat() { + return myStaticFloat; + } + + public static int getStaticInt() { + return myStaticInt; + } + + public static long getStaticLong() { + return myStaticLong; + } + + public static Object getStaticObject() { + return (Object) new String(myStaticObject); + } + + public static short getStaticShort() { + return myStaticShort; + } + + /* Ridiculous name and useless method, but this removes needing a + * special case for testing CallStaticVoidMethod[A|V] probes. */ + public static void getStaticVoid() { + return; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/RunWrapper.java Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,21 @@ +package staptest; + +import java.lang.reflect.Method; + +public class RunWrapper { + public static void main(String[] args) { + if (args.length >= 1) { + try { + Class<?> mainClass = RunWrapper.class. + getClassLoader().loadClass(args[0]); + Class[] types = new Class[] { args.getClass() }; + Method main = mainClass.getDeclaredMethod( + "main", types); + String[] runArgs = new String[args.length-1]; + System.arraycopy(args, 1, runArgs, 0, + runArgs.length); + main.invoke(null, new Object[] { runArgs }); + } catch (Exception ignore) {} + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/StapJNIClassLoader.java Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,64 @@ +package staptest; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; + +/* Loads classes only in default package in working directory, must be + * under 4096 bytes. Intentionally breaks classloader hierarchy. + */ +public class StapJNIClassLoader extends ClassLoader { + + public StapJNIClassLoader() { + super(); + } + + public StapJNIClassLoader(ClassLoader parent) { + super(parent); + } + + private static final int BUF_LEN = 4096; + + protected synchronized Class loadClass(String className, + boolean resolve) throws ClassNotFoundException { + Class aClass = findLoadedClass(className); + + if (aClass != null) { + return aClass; + } + + String fileName = className.replace('.', '/').concat(".class"); + byte[] classBytes = null; + try { + InputStream classIn = getResourceAsStream(fileName); + byte[] buffer = new byte[BUF_LEN]; + ByteArrayOutputStream temp = new ByteArrayOutputStream(); + int bytes_read = -1; + while ((bytes_read = classIn.read(buffer, 0, BUF_LEN)) != -1) { + temp.write(buffer, 0, bytes_read); + } + classBytes = temp.toByteArray(); + } catch (IOException ignore) { + // Possible error condition(s) resulting from thrown + // exception checked after. + } + + if (classBytes == null) { + throw new ClassNotFoundException("Could not load class: " + className); + } + + try { + aClass = defineClass(className, classBytes, 0, classBytes.length); + if (aClass == null) { + System.out.println("Gaah!"); + } + if (resolve) { + resolveClass(aClass); + } + } catch (SecurityException ex) { + aClass = super.loadClass(className, resolve); + } + + return aClass; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/StapURLClassLoader.java Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,24 @@ +package staptest; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +/* Let superclass handle everything, we just need a separate Classloader that + * will be unloaded (along with classes and their associated hot-compiled + * methods) while testing the hotspot.compiled_method_unload probe. + */ +public class StapURLClassLoader extends URLClassLoader { + public StapURLClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } + + public Class loadClass(String name) throws ClassNotFoundException { + return super.loadClass(name); + } + + protected Class findClass(String name) throws ClassNotFoundException { + return super.findClass(name); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/SystemtapTester.java Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,202 @@ +package staptest; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +public class SystemtapTester { + static String throwAwayString; + public static void main(String[] args) { + SystemtapTester tester = new SystemtapTester(); + throwAwayString = (args.length < 1 ? "NOTHING" + : ("ARG: " + args[0])); + System.out.println(throwAwayString); + if (args.length < 1) { + System.exit(1); + } else if (args[0].equals("vm_init_begin") || + args[0].equals("vm_init_end") || + args[0].equals("vm_shutdown") || + args[0].equals("object_alloc") || + args[0].equals("method_entry") || + args[0].equals("method_return")) { + // In this case, hotspot has already triggered these + // probes (or will shortly). No need to continue. + System.exit(0); + } else if (args[0].equals("gc_begin") || + args[0].equals("gc_end") || + args[0].equals("mem_pool_gc_begin") || + args[0].equals("mem_pool_gc_end")) { + tester.triggerGarbageCollect(); + } else if (args[0].equals("method_compile_begin") || + args[0].equals("method_compile_end") || + args[0].equals("compiled_method_load")) { + tester.triggerCompileMethod(); + // The jit compiler might be working in the background + // wait a little to make sure it is finished. Then + // repeat the test with a "hot jit". + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { } + tester.triggerCompileMethod(); + } else if (args[0].equals("compiled_method_unload")) { + tester.triggerUnloadMethod(); + // The jit compiler might be working in the background + // wait a little to make sure it is finished. Then + // repeat the test with a "hot jit". + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { } + tester.triggerUnloadMethod(); + } else if (args[0].equals("thread_start") || + args[0].equals("thread_stop")) { + tester.triggerThread(); + } else if (args[0].equals("class_loaded") || + args[0].equals("class_unloaded")) { + tester.triggerClassLoader(); + tester.triggerGarbageCollect(); + } else if (args[0].equals("monitor_contended_enter") || + args[0].equals("monitor_contended_entered") || + args[0].equals("monitor_contended_exit")) { + tester.triggerContended(); + } else if (args[0].equals("monitor_wait") || + args[0].equals("monitor_waited") || + args[0].equals("monitor_notify")) { + tester.triggerWait(TestingRunner.NOTIFY); + } else if (args[0].equals("monitor_notifyAll")) { + tester.triggerWait(TestingRunner.NOTIFYALL); + } + System.out.println(throwAwayString); + } + + public void triggerGarbageCollect() { + for (int i = 0; i < 1000; i++) { + throwAwayString = allocateForNoReason(i); + } + forceGarbageCollect(); + } + + public void triggerThread() { + Thread basicThread = new Thread( + new TestingRunner(TestingRunner.NOOP)); + basicThread.start(); + while (basicThread.isAlive()) { + try { + basicThread.join(); + } catch (Exception ignore) {} + } + } + + public void triggerCompileMethod() { + for (int i = 0; i < 105; i++) { + Integer iobj = new Integer(i); + throwAwayString = triggerCompileMethodLoop(iobj); + } + } + + public String triggerCompileMethodLoop(Integer iobj) { + for (int i = 0; i < 105; i++) { + throwAwayString = allocateForNoReason(iobj.intValue()); + } + return throwAwayString; + } + + public void triggerUnloadMethod() { + try { + ClassLoader base = ClassLoader.getSystemClassLoader(); + URL[] urls; + if (base instanceof URLClassLoader) { + urls = ((URLClassLoader) base).getURLs(); + } else { + urls = new URL[] { + new File(".").toURI().toURL() }; + } + StapURLClassLoader loader = new StapURLClassLoader( + urls, base.getParent()); + Class<?> runClass = loader.loadClass("staptest.RunWrapper"); + String[] aargs = new String[] { "staptest.RunWrapper", + "staptest.ClassUnloadedProbeTester"}; + Class[] argTypes = new Class[] { aargs.getClass() }; + Method main = runClass.getDeclaredMethod("main", argTypes); + String[] bargs = new String[1]; + bargs[0] = new String(aargs[1]); + Thread.currentThread().setContextClassLoader(loader); + main.invoke(null, new Object[] { bargs }); + Thread.currentThread().setContextClassLoader(base); + loader = null; + runClass = null; + } catch (Exception ex) { + ex.printStackTrace(); + } + triggerGarbageCollect(); + } + + public void triggerClassLoader() { + ThreadGroup aThreadGroup = new ThreadGroup("CustomClassLoadingThreadGroup"); + Thread classLoadingThread = new Thread(aThreadGroup, + new TestingRunner(TestingRunner.LOADER)); + classLoadingThread.start(); + while (classLoadingThread.isAlive()) { + try { + classLoadingThread.join(); + } catch (Exception ignore) {} + } + aThreadGroup.destroy(); + } + + public void triggerContended() { + Thread contendThread1 = + new Thread(new TestingRunner(TestingRunner.CONTENDER)); + Thread contendThread2 = + new Thread(new TestingRunner(TestingRunner.CONTENDER)); + contendThread1.start(); + contendThread2.start(); + while (contendThread1.isAlive() || contendThread2.isAlive()) { + try { + contendThread1.join(); + contendThread2.join(); + } catch (Exception ignore) {} + } + } + + public void triggerWait(int whichNotify) { + TestingRunner myRunner = new TestingRunner(whichNotify); + Thread target = new Thread(myRunner); + synchronized (myRunner) { + target.start(); + try { + myRunner.wait(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + while (target.isAlive()) { + try { + target.join(); + } catch (Exception ignore) { + } + } + } + + private void forceGarbageCollect() { + Runtime rt = Runtime.getRuntime(); + long memFree = rt.freeMemory(); + long beginTime = System.currentTimeMillis(); + long currentTime = beginTime; + do { + rt.gc(); + try { + Thread.sleep(1000); + } catch (Exception ignore) {} + currentTime = System.currentTimeMillis(); + } while ((memFree <= rt.freeMemory()) && + ((currentTime - beginTime) < 5000)); + } + + String allocateForNoReason(int i) { + String aString = new String("sometextinastring" + i); + return aString; + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/TestingRunner.java Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,82 @@ +package staptest; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +public class TestingRunner implements Runnable { + public static int NOOP = 0; + public static int LOADER = 1; + public static int CONTENDER = 2; + public static int NOTIFY = 3; + public static int NOTIFYALL = 4; + + private int myType; + + public TestingRunner(int type) { + myType = type; + } + + public void run() { + if (myType == LOADER) { + doLoadClass(); + } else if (myType == CONTENDER) { + doSynchronized(); + } else if (myType == NOTIFY) { + doNotify(); + } else if (myType == NOTIFYALL) { + doNotifyAll(); + } + } + + private void doLoadClass() { + /* We really just want to load the class and then let it + * get garbage collected. + */ + try { + ClassLoader base = ClassLoader.getSystemClassLoader(); + URL[] urls; + if (base instanceof URLClassLoader) { + urls = ((URLClassLoader) base).getURLs(); + } else { + urls = new URL[] { + new File(".").toURI().toURL() }; + } + StapURLClassLoader loader = new StapURLClassLoader( + urls, base.getParent()); + Class testClass = Class.forName("staptest.ClassUnloadedProbeTester", true, loader); + testClass = null; + loader = null; + } catch (Exception ignore) { + ignore.printStackTrace(); + } + } + + private void doNotify() { + synchronized (this) { + waitFiveSeconds(); + notify(); + } + } + + private void doNotifyAll() { + synchronized (this) { + waitFiveSeconds(); + notifyAll(); + } + } + + private static synchronized void doSynchronized() { + int anInt = 5; + for (int i = 0; i < 10; i++) { + anInt += i; + } + waitFiveSeconds(); + } + + private static void waitFiveSeconds() { + try { + Thread.sleep(5000); + } catch (Exception ignore) {} + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tapset/jstaptest.pl Fri Mar 23 14:11:00 2012 +0100 @@ -0,0 +1,954 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Config; +# For log file. +use File::Basename; +use File::Path; +my $log_file; +my $logfile_name; + +# For parsing options. +use Getopt::Std; +$Getopt::Std::OUTPUT_HELP_VERSION = 1; +# sub main::HELP_MESSAGE defined below. +our($opt_B, $opt_A, $opt_o, $opt_a, $opt_S, $opt_J); + +# Gigantic nested array. +# Each element in outer array should be of the form: +# ["<NAME>", "<PRINTARG>", "<TARGET>"] +# NAME is the name of a probe alias. +# PRINTARG is a (quoted, escaped) format string along with additional variable +# arguments, separated by commas, that will be inserted as the arguments to +# a printf() call in a systemtap script. +# TARGET is the expected output of the probe firing in a test, or (where exact +# output is not known) a matching regex. +my @probestrings = (["hotspot.gc_begin", "\"%s\\n\",name", "^gc_begin\$"], + ["hotspot.gc_end", "\"%s\\n\",name", "^gc_end\$"], + ["hotspot.mem_pool_gc_begin", "\"%s\\n\",name", "^mem_pool_gc_begin\$"], + ["hotspot.mem_pool_gc_end", "\"%s\\n\",name", "^mem_pool_gc_end\$"], + ["hotspot.object_alloc", "\"%stid=%dclass=%s\\n\",name,thread_id,class", "^object_alloctid=1class=staptest/SystemtapTester\$"], + ["hotspot.vm_init_begin", "\"%s\\n\",name", "^vm_init_begin\$"], + ["hotspot.vm_init_end", "\"%s\\n\",name", "^vm_init_end\$"], + ["hotspot.vm_shutdown", "\"%s\\n\",name", "^vm_shutdown\$"], + ["hotspot.thread_start", "\"%sname=%stid=%dd=%d\\n\",name,thread_name,id,is_daemon", "^thread_startname=Thread-0tid=8d=0\$"], + ["hotspot.thread_stop", "\"%sname=%stid=%dd=%d\\n\",name,thread_name,id,is_daemon", "^thread_stopname=Thread-0tid=8d=0\$"], + ["hotspot.class_loaded", "\"%sclass=%ssh=%d\\n\",name,class,is_shared", "class_loadedclass=staptest/ClassUnloadedProbeTestersh=0"], + ["hotspot.class_unloaded", "\"%sclass=%ssh=%d\\n\",name,class,is_shared", "class_unloadedclass=staptest/ClassUnloadedProbeTestersh=0"], + ["hotspot.method_compile_begin", "\"%sclass=%smethod=%ssig=%s\\n\",name,class,method,sig", "method_compile_beginclass=staptest/SystemtapTestermethod=allocateForNoReasonsig=(I)Ljava/lang/String;"], + ["hotspot.method_compile_end", "\"%sclass=%smethod=%ssig=%s\\n\",name,class,method,sig", "method_compile_endclass=staptest/SystemtapTestermethod=allocateForNoReasonsig=(I)Ljava/lang/String;"], + ["hotspot.monitor_wait", "\"%sclass=%sto=%d\\n\",name,class,timeout", "monitor_waitclass=staptest/TestingRunnerto=0"], + ["hotspot.monitor_waited", "\"%sclass=%s\\n\",name,class", "monitor_waitedclass=staptest/TestingRunner"], + ["hotspot.monitor_notify", "\"%sclass=%s\\n\",name,class", "monitor_notifyclass=staptest/TestingRunner"], + ["hotspot.monitor_notifyAll", "\"%sclass=%s\\n\",name,class", "monitor_notifyAllclass=staptest/TestingRunner"], + ["hotspot.monitor_contended_enter", "\"%sclass=%s\\n\",name,class", "monitor_contended_enterclass=java/lang/Class"], + ["hotspot.monitor_contended_entered", "\"%sclass=%s\\n\",name,class", "monitor_contended_enteredclass=java/lang/Class"], + ["hotspot.monitor_contended_exit", "\"%sclass=%s\\n\",name,class", "monitor_contended_exitclass=java/lang/Class"], + ["hotspot.method_entry", "\"%sclass=%smethod=%ssig=%s\\n\",name,class,method,sig", "method_entryclass=staptest/SystemtapTestermethod=<init>sig=()V"], + ["hotspot.method_return", "\"%sclass=%smethod=%ssig=%s\\n\",name,class,method,sig", "method_returnclass=staptest/SystemtapTestermethod=<init>sig=()V"], + ["hotspot.compiled_method_load", "\"%sclass=%smethod=%ssig=%s\\n\",name,class,method,sig", "compiled_method_loadclass=staptest/SystemtapTestermethod=allocateForNoReasonsig=(I)Ljava/lang/String;"], + ["hotspot.compiled_method_unload", "\"%sclass=%smethod=%ssig=%s\\n\",name,class,method,sig", "compiled_method_unloadclass=staptest/ClassUnloadedProbeTestermethod=setFieldsig=(I)V"], + ["hotspot.jni.AllocObject", "\"%s\\n\",name", "AllocObject"], + ["hotspot.jni.AllocObject.return", "\"%sret=%d\\n\",name,ret", "AllocObjectret=[^0]"], + ["hotspot.jni.AttachCurrentThreadAsDaemon", "\"%s\\n\",name", "AttachCurrentThreadAsDaemon"], + ["hotspot.jni.AttachCurrentThreadAsDaemon.return", "\"%sret=%d\\n\",name,ret", "AttachCurrentThreadAsDaemonret=0"], + ["hotspot.jni.AttachCurrentThread", "\"%s\\n\",name", "AttachCurrentThread"], + ["hotspot.jni.AttachCurrentThread.return", "\"%sret=%d\\n\",name,ret", "AttachCurrentThreadret=0"], + ["hotspot.jni.CallBooleanMethodA", "\"%s\\n\",name", "CallBooleanMethodA"], + ["hotspot.jni.CallBooleanMethodA.return", "\"%sret=%d\\n\",name,ret", "CallBooleanMethodAret=1"], + ["hotspot.jni.CallBooleanMethod", "\"%s\\n\",name", "CallBooleanMethod"], + ["hotspot.jni.CallBooleanMethod.return", "\"%sret=%d\\n\",name,ret", "CallBooleanMethodret=1"], + ["hotspot.jni.CallBooleanMethodV", "\"%s\\n\",name", "CallBooleanMethodV"], + ["hotspot.jni.CallBooleanMethodV.return", "\"%sret=%d\\n\",name,ret", "CallBooleanMethodVret=1"], + ["hotspot.jni.CallByteMethodA", "\"%s\\n\",name", "CallByteMethodA"], + ["hotspot.jni.CallByteMethodA.return", "\"%sret=%d\\n\",name,ret", "CallByteMethodAret=0"], + ["hotspot.jni.CallByteMethod", "\"%s\\n\",name", "CallByteMethod"], + ["hotspot.jni.CallByteMethod.return", "\"%sret=%d\\n\",name,ret", "CallByteMethodret=0"], + ["hotspot.jni.CallByteMethodV", "\"%s\\n\",name", "CallByteMethodV"], + ["hotspot.jni.CallByteMethodV.return", "\"%sret=%d\\n\",name,ret", "CallByteMethodVret=0"], + ["hotspot.jni.CallCharMethodA", "\"%s\\n\",name", "CallCharMethodA"], + ["hotspot.jni.CallCharMethodA.return", "\"%sret=%d\\n\",name,ret", "CallCharMethodAret=97"], + ["hotspot.jni.CallCharMethod", "\"%s\\n\",name", "CallCharMethod"], + ["hotspot.jni.CallCharMethod.return", "\"%sret=%d\\n\",name,ret", "CallCharMethodret=97"], + ["hotspot.jni.CallCharMethodV", "\"%s\\n\",name", "CallCharMethodV"], + ["hotspot.jni.CallCharMethodV.return", "\"%sret=%d\\n\",name,ret", "CallCharMethodVret=97"], + ["hotspot.jni.CallDoubleMethodA", "\"%s\\n\",name", "CallDoubleMethodA"], + ["hotspot.jni.CallDoubleMethodA.return", "\"%s\\n\",name", "CallDoubleMethodA"], + ["hotspot.jni.CallDoubleMethod", "\"%s\\n\",name", "CallDoubleMethod"], + ["hotspot.jni.CallDoubleMethod.return", "\"%s\\n\",name", "CallDoubleMethod"], + ["hotspot.jni.CallDoubleMethodV", "\"%s\\n\",name", "CallDoubleMethodV"], + ["hotspot.jni.CallDoubleMethodV.return", "\"%s\\n\",name", "CallDoubleMethodV"], + ["hotspot.jni.CallFloatMethodA", "\"%s\\n\",name", "CallFloatMethodA"], + ["hotspot.jni.CallFloatMethodA.return", "\"%s\\n\",name", "CallFloatMethodA"], + ["hotspot.jni.CallFloatMethod", "\"%s\\n\",name", "CallFloatMethod"], + ["hotspot.jni.CallFloatMethod.return", "\"%s\\n\",name", "CallFloatMethod"], + ["hotspot.jni.CallFloatMethodV", "\"%s\\n\",name", "CallFloatMethodV"], + ["hotspot.jni.CallFloatMethodV.return", "\"%s\\n\",name", "CallFloatMethodV"], + ["hotspot.jni.CallIntMethodA", "\"%s\\n\",name", "CallIntMethodA"], + ["hotspot.jni.CallIntMethodA.return", "\"%sret=%d\\n\",name,ret", "CallIntMethodAret=4"], + ["hotspot.jni.CallIntMethod", "\"%s\\n\",name", "CallIntMethod"], + ["hotspot.jni.CallIntMethod.return", "\"%sret=%d\\n\",name,ret", "CallIntMethodret=4"], + ["hotspot.jni.CallIntMethodV", "\"%s\\n\",name", "CallIntMethodV"], + ["hotspot.jni.CallIntMethodV.return", "\"%sret=%d\\n\",name,ret", "CallIntMethodVret=4"], + ["hotspot.jni.CallLongMethodA", "\"%s\\n\",name", "CallLongMethodA"], + ["hotspot.jni.CallLongMethodA.return", "\"%sret=%d\\n\",name,ret", "CallLongMethodAret=8"], + ["hotspot.jni.CallLongMethod", "\"%s\\n\",name", "CallLongMethod"], + ["hotspot.jni.CallLongMethod.return", "\"%sret=%d\\n\",name,ret", "CallLongMethodret=8"], + ["hotspot.jni.CallLongMethodV", "\"%s\\n\",name", "CallLongMethodV"], + ["hotspot.jni.CallLongMethodV.return", "\"%sret=%d\\n\",name,ret", "CallLongMethodVret=8"], + ["hotspot.jni.CallObjectMethodA", "\"%s\\n\",name", "CallObjectMethodA"], + ["hotspot.jni.CallObjectMethodA.return", "\"%s\\n\",name", "CallObjectMethodA"], + ["hotspot.jni.CallObjectMethod", "\"%s\\n\",name", "CallObjectMethod"], + ["hotspot.jni.CallObjectMethod.return", "\"%s\\n\",name", "CallObjectMethod"], + ["hotspot.jni.CallObjectMethodV", "\"%s\\n\",name", "CallObjectMethodV"], + ["hotspot.jni.CallObjectMethodV.return", "\"%s\\n\",name", "CallObjectMethodV"], + ["hotspot.jni.CallShortMethodA", "\"%s\\n\",name", "CallShortMethodA"], + ["hotspot.jni.CallShortMethodA.return", "\"%sret=%d\\n\",name,ret", "CallShortMethodAret=2"], + ["hotspot.jni.CallShortMethod", "\"%s\\n\",name", "CallShortMethod"], + ["hotspot.jni.CallShortMethod.return", "\"%sret=%d\\n\",name,ret", "CallShortMethodret=2"], + ["hotspot.jni.CallShortMethodV", "\"%s\\n\",name", "CallShortMethodV"], + ["hotspot.jni.CallShortMethodV.return", "\"%sret=%d\\n\",name,ret", "CallShortMethodVret=2"], + ["hotspot.jni.CallVoidMethodA", "\"%s\\n\",name", "CallVoidMethodA"], + ["hotspot.jni.CallVoidMethodA.return", "\"%s\\n\",name", "CallVoidMethodA"], + ["hotspot.jni.CallVoidMethod", "\"%s\\n\",name", "CallVoidMethod"], + ["hotspot.jni.CallVoidMethod.return", "\"%s\\n\",name", "CallVoidMethod"], + ["hotspot.jni.CallVoidMethodV", "\"%s\\n\",name", "CallVoidMethodV"], + ["hotspot.jni.CallVoidMethodV.return", "\"%s\\n\",name", "CallVoidMethodV"], + ["hotspot.jni.CallNonvirtualBooleanMethodA", "\"%s\\n\",name", "CallNonvirtualBooleanMethodA"], + ["hotspot.jni.CallNonvirtualBooleanMethodA.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualBooleanMethodAret=1"], + ["hotspot.jni.CallNonvirtualBooleanMethod", "\"%s\\n\",name", "CallNonvirtualBooleanMethod"], + ["hotspot.jni.CallNonvirtualBooleanMethod.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualBooleanMethodret=1"], + ["hotspot.jni.CallNonvirtualBooleanMethodV", "\"%s\\n\",name", "CallNonvirtualBooleanMethodV"], + ["hotspot.jni.CallNonvirtualBooleanMethodV.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualBooleanMethodVret=1"], + ["hotspot.jni.CallNonvirtualByteMethodA", "\"%s\\n\",name", "CallNonvirtualByteMethodA"], + ["hotspot.jni.CallNonvirtualByteMethodA.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualByteMethodAret=0"], + ["hotspot.jni.CallNonvirtualByteMethod", "\"%s\\n\",name", "CallNonvirtualByteMethod"], + ["hotspot.jni.CallNonvirtualByteMethod.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualByteMethodret=0"], + ["hotspot.jni.CallNonvirtualByteMethodV", "\"%s\\n\",name", "CallNonvirtualByteMethodV"], + ["hotspot.jni.CallNonvirtualByteMethodV.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualByteMethodVret=0"], + ["hotspot.jni.CallNonvirtualCharMethodA", "\"%s\\n\",name", "CallNonvirtualCharMethodA"], + ["hotspot.jni.CallNonvirtualCharMethodA.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualCharMethodAret=97"], + ["hotspot.jni.CallNonvirtualCharMethod", "\"%s\\n\",name", "CallNonvirtualCharMethod"], + ["hotspot.jni.CallNonvirtualCharMethod.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualCharMethodret=97"], + ["hotspot.jni.CallNonvirtualCharMethodV", "\"%s\\n\",name", "CallNonvirtualCharMethodV"], + ["hotspot.jni.CallNonvirtualCharMethodV.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualCharMethodVret=97"], + ["hotspot.jni.CallNonvirtualDoubleMethodA", "\"%s\\n\",name", "CallNonvirtualDoubleMethodA"], + ["hotspot.jni.CallNonvirtualDoubleMethodA.return", "\"%s\\n\",name", "CallNonvirtualDoubleMethodA"], + ["hotspot.jni.CallNonvirtualDoubleMethod", "\"%s\\n\",name", "CallNonvirtualDoubleMethod"], + ["hotspot.jni.CallNonvirtualDoubleMethod.return", "\"%s\\n\",name", "CallNonvirtualDoubleMethod"], + ["hotspot.jni.CallNonvirtualDoubleMethodV", "\"%s\\n\",name", "CallNonvirtualDoubleMethodV"], + ["hotspot.jni.CallNonvirtualDoubleMethodV.return", "\"%s\\n\",name", "CallNonvirtualDoubleMethodV"], + ["hotspot.jni.CallNonvirtualFloatMethodA", "\"%s\\n\",name", "CallNonvirtualFloatMethodA"], + ["hotspot.jni.CallNonvirtualFloatMethodA.return", "\"%s\\n\",name", "CallNonvirtualFloatMethodA"], + ["hotspot.jni.CallNonvirtualFloatMethod", "\"%s\\n\",name", "CallNonvirtualFloatMethod"], + ["hotspot.jni.CallNonvirtualFloatMethod.return", "\"%s\\n\",name", "CallNonvirtualFloatMethod"], + ["hotspot.jni.CallNonvirtualFloatMethodV", "\"%s\\n\",name", "CallNonvirtualFloatMethodV"], + ["hotspot.jni.CallNonvirtualFloatMethodV.return", "\"%s\\n\",name", "CallNonvirtualFloatMethodV"], + ["hotspot.jni.CallNonvirtualIntMethodA", "\"%s\\n\",name", "CallNonvirtualIntMethodA"], + ["hotspot.jni.CallNonvirtualIntMethodA.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualIntMethodAret=4"], + ["hotspot.jni.CallNonvirtualIntMethod", "\"%s\\n\",name", "CallNonvirtualIntMethod"], + ["hotspot.jni.CallNonvirtualIntMethod.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualIntMethodret=4"], + ["hotspot.jni.CallNonvirtualIntMethodV", "\"%s\\n\",name", "CallNonvirtualIntMethodV"], + ["hotspot.jni.CallNonvirtualIntMethodV.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualIntMethodVret=4"], + ["hotspot.jni.CallNonvirtualLongMethodA", "\"%s\\n\",name", "CallNonvirtualLongMethodA"], + ["hotspot.jni.CallNonvirtualLongMethodA.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualLongMethodAret=8"], + ["hotspot.jni.CallNonvirtualLongMethod", "\"%s\\n\",name", "CallNonvirtualLongMethod"], + ["hotspot.jni.CallNonvirtualLongMethod.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualLongMethodret=8"], + ["hotspot.jni.CallNonvirtualLongMethodV", "\"%s\\n\",name", "CallNonvirtualLongMethodV"], + ["hotspot.jni.CallNonvirtualLongMethodV.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualLongMethodVret=8"], + ["hotspot.jni.CallNonvirtualObjectMethodA", "\"%s\\n\",name", "CallNonvirtualObjectMethodA"], + ["hotspot.jni.CallNonvirtualObjectMethodA.return", "\"%s\\n\",name", "CallNonvirtualObjectMethodA"], + ["hotspot.jni.CallNonvirtualObjectMethod", "\"%s\\n\",name", "CallNonvirtualObjectMethod"], + ["hotspot.jni.CallNonvirtualObjectMethod.return", "\"%s\\n\",name", "CallNonvirtualObjectMethod"], + ["hotspot.jni.CallNonvirtualObjectMethodV", "\"%s\\n\",name", "CallNonvirtualObjectMethodV"], + ["hotspot.jni.CallNonvirtualObjectMethodV.return", "\"%s\\n\",name", "CallNonvirtualObjectMethodV"], + ["hotspot.jni.CallNonvirtualShortMethodA", "\"%s\\n\",name", "CallNonvirtualShortMethodA"], + ["hotspot.jni.CallNonvirtualShortMethodA.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualShortMethodAret=2"], + ["hotspot.jni.CallNonvirtualShortMethod", "\"%s\\n\",name", "CallNonvirtualShortMethod"], + ["hotspot.jni.CallNonvirtualShortMethod.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualShortMethodret=2"], + ["hotspot.jni.CallNonvirtualShortMethodV", "\"%s\\n\",name", "CallNonvirtualShortMethodV"], + ["hotspot.jni.CallNonvirtualShortMethodV.return", "\"%sret=%d\\n\",name,ret", "CallNonvirtualShortMethodVret=2"], + ["hotspot.jni.CallNonvirtualVoidMethodA", "\"%s\\n\",name", "CallNonvirtualVoidMethodA"], + ["hotspot.jni.CallNonvirtualVoidMethodA.return", "\"%s\\n\",name", "CallNonvirtualVoidMethodA"], + ["hotspot.jni.CallNonvirtualVoidMethod", "\"%s\\n\",name", "CallNonvirtualVoidMethod"], + ["hotspot.jni.CallNonvirtualVoidMethod.return", "\"%s\\n\",name", "CallNonvirtualVoidMethod"], + ["hotspot.jni.CallNonvirtualVoidMethodV", "\"%s\\n\",name", "CallNonvirtualVoidMethodV"], + ["hotspot.jni.CallNonvirtualVoidMethodV.return", "\"%s\\n\",name", "CallNonvirtualVoidMethodV"], + ["hotspot.jni.CallStaticBooleanMethodA", "\"%s\\n\",name", "CallStaticBooleanMethodA"], + ["hotspot.jni.CallStaticBooleanMethodA.return", "\"%sret=%d\\n\",name,ret", "CallStaticBooleanMethodAret=0"], + ["hotspot.jni.CallStaticBooleanMethod", "\"%s\\n\",name", "CallStaticBooleanMethod"], + ["hotspot.jni.CallStaticBooleanMethod.return", "\"%sret=%d\\n\",name,ret", "CallStaticBooleanMethodret=0"], + ["hotspot.jni.CallStaticBooleanMethodV", "\"%s\\n\",name", "CallStaticBooleanMethodV"], + ["hotspot.jni.CallStaticBooleanMethodV.return", "\"%sret=%d\\n\",name,ret", "CallStaticBooleanMethodVret=0"], + ["hotspot.jni.CallStaticByteMethodA", "\"%s\\n\",name", "CallStaticByteMethodA"], + ["hotspot.jni.CallStaticByteMethodA.return", "\"%sret=%d\\n\",name,ret", "CallStaticByteMethodAret=1"], + ["hotspot.jni.CallStaticByteMethod", "\"%s\\n\",name", "CallStaticByteMethod"], + ["hotspot.jni.CallStaticByteMethod.return", "\"%sret=%d\\n\",name,ret", "CallStaticByteMethodret=1"], + ["hotspot.jni.CallStaticByteMethodV", "\"%s\\n\",name", "CallStaticByteMethodV"], + ["hotspot.jni.CallStaticByteMethodV.return", "\"%sret=%d\\n\",name,ret", "CallStaticByteMethodVret=1"], + ["hotspot.jni.CallStaticCharMethodA", "\"%s\\n\",name", "CallStaticCharMethodA"], + ["hotspot.jni.CallStaticCharMethodA.return", "\"%sret=%d\\n\",name,ret", "CallStaticCharMethodAret=98"], + ["hotspot.jni.CallStaticCharMethod", "\"%s\\n\",name", "CallStaticCharMethod"], + ["hotspot.jni.CallStaticCharMethod.return", "\"%sret=%d\\n\",name,ret", "CallStaticCharMethodret=98"], + ["hotspot.jni.CallStaticCharMethodV", "\"%s\\n\",name", "CallStaticCharMethodV"], + ["hotspot.jni.CallStaticCharMethodV.return", "\"%sret=%d\\n\",name,ret", "CallStaticCharMethodVret=98"], + ["hotspot.jni.CallStaticDoubleMethodA", "\"%s\\n\",name", "CallStaticDoubleMethodA"], + ["hotspot.jni.CallStaticDoubleMethodA.return", "\"%s\\n\",name", "CallStaticDoubleMethodA"], + ["hotspot.jni.CallStaticDoubleMethod", "\"%s\\n\",name", "CallStaticDoubleMethod"], + ["hotspot.jni.CallStaticDoubleMethod.return", "\"%s\\n\",name", "CallStaticDoubleMethod"], + ["hotspot.jni.CallStaticDoubleMethodV", "\"%s\\n\",name", "CallStaticDoubleMethodV"], + ["hotspot.jni.CallStaticDoubleMethodV.return", "\"%s\\n\",name", "CallStaticDoubleMethodV"], + ["hotspot.jni.CallStaticFloatMethodA", "\"%s\\n\",name", "CallStaticFloatMethodA"], + ["hotspot.jni.CallStaticFloatMethodA.return", "\"%s\\n\",name", "CallStaticFloatMethodA"], + ["hotspot.jni.CallStaticFloatMethod", "\"%s\\n\",name", "CallStaticFloatMethod"], + ["hotspot.jni.CallStaticFloatMethod.return", "\"%s\\n\",name", "CallStaticFloatMethod"], + ["hotspot.jni.CallStaticFloatMethodV", "\"%s\\n\",name", "CallStaticFloatMethodV"], + ["hotspot.jni.CallStaticFloatMethodV.return", "\"%s\\n\",name", "CallStaticFloatMethodV"], + ["hotspot.jni.CallStaticIntMethodA", "\"%s\\n\",name", "CallStaticIntMethodA"], + ["hotspot.jni.CallStaticIntMethodA.return", "\"%sret=%d\\n\",name,ret", "CallStaticIntMethodAret=32"], + ["hotspot.jni.CallStaticIntMethod", "\"%s\\n\",name", "CallStaticIntMethod"], + ["hotspot.jni.CallStaticIntMethod.return", "\"%sret=%d\\n\",name,ret", "CallStaticIntMethodret=32"], + ["hotspot.jni.CallStaticIntMethodV", "\"%s\\n\",name", "CallStaticIntMethodV"], + ["hotspot.jni.CallStaticIntMethodV.return", "\"%sret=%d\\n\",name,ret", "CallStaticIntMethodVret=32"], + ["hotspot.jni.CallStaticLongMethodA", "\"%s\\n\",name", "CallStaticLongMethodA"], + ["hotspot.jni.CallStaticLongMethodA.return", "\"%sret=%d\\n\",name,ret", "CallStaticLongMethodAret=64"], + ["hotspot.jni.CallStaticLongMethod", "\"%s\\n\",name", "CallStaticLongMethod"], + ["hotspot.jni.CallStaticLongMethod.return", "\"%sret=%d\\n\",name,ret", "CallStaticLongMethodret=64"], + ["hotspot.jni.CallStaticLongMethodV", "\"%s\\n\",name", "CallStaticLongMethodV"], + ["hotspot.jni.CallStaticLongMethodV.return", "\"%sret=%d\\n\",name,ret", "CallStaticLongMethodVret=64"], + ["hotspot.jni.CallStaticObjectMethodA", "\"%s\\n\",name", "CallStaticObjectMethodA"], + ["hotspot.jni.CallStaticObjectMethodA.return", "\"%s\\n\",name", "CallStaticObjectMethodA"], + ["hotspot.jni.CallStaticObjectMethod", "\"%s\\n\",name", "CallStaticObjectMethod"], + ["hotspot.jni.CallStaticObjectMethod.return", "\"%s\\n\",name", "CallStaticObjectMethod"], + ["hotspot.jni.CallStaticObjectMethodV", "\"%s\\n\",name", "CallStaticObjectMethodV"], + ["hotspot.jni.CallStaticObjectMethodV.return", "\"%s\\n\",name", "CallStaticObjectMethodV"], + ["hotspot.jni.CallStaticShortMethodA", "\"%s\\n\",name", "CallStaticShortMethodA"], + ["hotspot.jni.CallStaticShortMethodA.return", "\"%sret=%d\\n\",name,ret", "CallStaticShortMethodAret=16"], + ["hotspot.jni.CallStaticShortMethod", "\"%s\\n\",name", "CallStaticShortMethod"], + ["hotspot.jni.CallStaticShortMethod.return", "\"%sret=%d\\n\",name,ret", "CallStaticShortMethodret=16"], + ["hotspot.jni.CallStaticShortMethodV", "\"%s\\n\",name", "CallStaticShortMethodV"], + ["hotspot.jni.CallStaticShortMethodV.return", "\"%sret=%d\\n\",name,ret", "CallStaticShortMethodVret=16"], + ["hotspot.jni.CallStaticVoidMethodA", "\"%s\\n\",name", "CallStaticVoidMethodA"], + ["hotspot.jni.CallStaticVoidMethodA.return", "\"%s\\n\",name", "CallStaticVoidMethodA"], + ["hotspot.jni.CallStaticVoidMethod", "\"%s\\n\",name", "CallStaticVoidMethod"], + ["hotspot.jni.CallStaticVoidMethod.return", "\"%s\\n\",name", "CallStaticVoidMethod"], + ["hotspot.jni.CallStaticVoidMethodV", "\"%s\\n\",name", "CallStaticVoidMethodV"], + ["hotspot.jni.CallStaticVoidMethodV.return", "\"%s\\n\",name", "CallStaticVoidMethodV"], + ["hotspot.jni.CreateJavaVM", "\"%s\\n\",name", "CreateJavaVM"], + ["hotspot.jni.CreateJavaVM.return", "\"%sret=%d\\n\",name,ret", "CreateJavaVMret=0"], + ["hotspot.jni.DefineClass", "\"%sclass=%s\\n\",name,clazz", "DefineClassclass=staptest/JNITestClass"], + ["hotspot.jni.DefineClass.return", "\"%sret=%d\\n\",name,ret", "DefineClassret=[^0]"], + ["hotspot.jni.DeleteGlobalRef", "\"%s\\n\",name", "DeleteGlobalRef"], + ["hotspot.jni.DeleteGlobalRef.return", "\"%s\\n\",name", "DeleteGlobalRef"], + ["hotspot.jni.DeleteLocalRef", "\"%s\\n\",name", "DeleteLocalRef"], + ["hotspot.jni.DeleteLocalRef.return", "\"%s\\n\",name", "DeleteLocalRef"], + ["hotspot.jni.DeleteWeakGlobalRef", "\"%s\\n\",name", "DeleteWeakGlobalRef"], + ["hotspot.jni.DeleteWeakGlobalRef.return", "\"%s\\n\",name", "DeleteWeakGlobalRef"], + ["hotspot.jni.DestroyJavaVM", "\"%s\\n\",name", "DestroyJavaVM"], + ["hotspot.jni.DestroyJavaVM.return", "\"%sret=%d\\n\",name,ret", "DestroyJavaVMret=0"], + ["hotspot.jni.DetachCurrentThread", "\"%s\\n\",name", "DetachCurrentThread"], + ["hotspot.jni.DetachCurrentThread.return", "\"%sret=%d\\n\",name,ret", "DetachCurrentThreadret=0"], + ["hotspot.jni.EnsureLocalCapacity", "\"%scap=%d\\n\",name,capacity", "EnsureLocalCapacitycap=10"], + ["hotspot.jni.EnsureLocalCapacity.return", "\"%sret=%d\\n\",name,ret", "EnsureLocalCapacityret=0"], + ["hotspot.jni.ExceptionCheck", "\"%s\\n\",name", "ExceptionCheck"], + ["hotspot.jni.ExceptionCheck.return", "\"%sret=%d\\n\",name,ret", "ExceptionCheckret=1"], + ["hotspot.jni.ExceptionClear", "\"%s\\n\",name", "ExceptionClear"], + ["hotspot.jni.ExceptionClear.return", "\"%s\\n\",name", "ExceptionClear"], + ["hotspot.jni.ExceptionDescribe", "\"%s\\n\",name", "ExceptionDescribe"], + ["hotspot.jni.ExceptionDescribe.return", "\"%s\\n\",name", "ExceptionDescribe"], + ["hotspot.jni.ExceptionOccurred", "\"%s\\n\",name", "ExceptionOccurred"], + ["hotspot.jni.ExceptionOccurred.return", "\"%sret=%d\\n\",name,ret", "ExceptionOccurredret=[^0]"], + ["hotspot.jni.FatalError", "\"%smsg=%s\\n\",name,msg", "FatalErrormsg=Intentional Crash: Ignore."], + ["hotspot.jni.FindClass", "\"%sclass=%s\\n\",name,clazz", "FindClassclass=staptest/JNITestClass"], + ["hotspot.jni.FindClass.return", "\"%sret=%d\\n\",name,ret", "FindClassret=[^0]"], + ["hotspot.jni.FromReflectedField", "\"%s\\n\",name", "FromReflectedField"], + ["hotspot.jni.FromReflectedField.return", "\"%s\\n\",name", "FromReflectedField"], + ["hotspot.jni.FromReflectedMethod", "\"%s\\n\",name", "FromReflectedMethod"], + ["hotspot.jni.FromReflectedMethod.return", "\"%s\\n\",name", "FromReflectedMethod"], + ["hotspot.jni.GetArrayLength", "\"%s\\n\",name", "GetArrayLength"], + ["hotspot.jni.GetArrayLength.return", "\"%sret=%d\\n\",name,ret", "GetArrayLengthret=5"], + ["hotspot.jni.GetBooleanArrayElements", "\"%scp=%d\\n\",name,iscopy", "GetBooleanArrayElementscp=0"], + ["hotspot.jni.GetBooleanArrayElements.return", "\"%sret=%d\\n\",name,ret", "GetBooleanArrayElementsret=[^0]"], + ["hotspot.jni.GetBooleanArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "GetBooleanArrayRegionstart=0len=5"], + ["hotspot.jni.GetBooleanArrayRegion.return", "\"%s\\n\",name", "GetBooleanArrayRegion"], + ["hotspot.jni.GetBooleanField", "\"%s\\n\",name", "GetBooleanField"], + ["hotspot.jni.GetBooleanField.return", "\"%sret=%d\\n\",name,ret", "GetBooleanFieldret=1"], + ["hotspot.jni.GetByteArrayElements", "\"%scp=%d\\n\",name,iscopy", "GetByteArrayElementscp=0"], + ["hotspot.jni.GetByteArrayElements.return", "\"%sret=%d\\n\",name,ret", "GetByteArrayElementsret=[^0]"], + ["hotspot.jni.GetByteArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "GetByteArrayRegionstart=0len=5"], + ["hotspot.jni.GetByteArrayRegion.return", "\"%s\\n\",name", "GetByteArrayRegion"], + ["hotspot.jni.GetByteField", "\"%s\\n\",name", "GetByteField"], + ["hotspot.jni.GetByteField.return", "\"%sret=%d\\n\",name,ret", "GetByteFieldret=0"], + ["hotspot.jni.GetCharArrayElements", "\"%scp=%d\\n\",name,iscopy", "GetCharArrayElementscp=0"], + ["hotspot.jni.GetCharArrayElements.return", "\"%sret=%d\\n\",name,ret", "GetCharArrayElementsret=[^0]"], + ["hotspot.jni.GetCharArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "GetCharArrayRegionstart=0len=5"], + ["hotspot.jni.GetCharArrayRegion.return", "\"%s\\n\",name", "GetCharArrayRegion"], + ["hotspot.jni.GetCharField", "\"%s\\n\",name", "GetCharField"], + ["hotspot.jni.GetCharField.return", "\"%sret=%d\\n\",name,ret", "GetCharFieldret=97"], + ["hotspot.jni.GetCreatedJavaVMs", "\"%sbuflen=%d\\n\",name,buflen", "GetCreatedJavaVMsbuflen=1"], + ["hotspot.jni.GetCreatedJavaVMs.return", "\"%sret=%d\\n\",name,ret", "GetCreatedJavaVMsret=0"], + ["hotspot.jni.GetDefaultJavaVMInitArgs", "\"%s\\n\",name", "GetDefaultJavaVMInitArgs"], + ["hotspot.jni.GetDefaultJavaVMInitArgs.return", "\"%sret=%d\\n\",name,ret", "GetDefaultJavaVMInitArgsret=0"], + ["hotspot.jni.GetDirectBufferAddress", "\"%s\\n\",name", "GetDirectBufferAddress"], + ["hotspot.jni.GetDirectBufferAddress.return", "\"%sret=%d\\n\",name,ret", "GetDirectBufferAddressret=[^0]"], + ["hotspot.jni.GetDirectBufferCapacity", "\"%s\\n\",name", "GetDirectBufferCapacity"], + ["hotspot.jni.GetDirectBufferCapacity.return", "\"%sret=%d\\n\",name,ret", "GetDirectBufferCapacityret=128"], + ["hotspot.jni.GetDoubleArrayElements", "\"%scp=%d\\n\",name,iscopy", "GetDoubleArrayElementscp=0"], + ["hotspot.jni.GetDoubleArrayElements.return", "\"%sret=%d\\n\",name,ret", "GetDoubleArrayElementsret=[^0]"], + ["hotspot.jni.GetDoubleArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "GetDoubleArrayRegionstart=0len=5"], + ["hotspot.jni.GetDoubleArrayRegion.return", "\"%s\\n\",name", "GetDoubleArrayRegion"], + ["hotspot.jni.GetDoubleField", "\"%s\\n\",name", "GetDoubleField"], + ["hotspot.jni.GetDoubleField.return", "\"%s\\n\",name", "GetDoubleField"], + ["hotspot.jni.GetEnv", "\"%sver=%x\\n\",name,version", "GetEnvver=10006"], + ["hotspot.jni.GetEnv.return", "\"%sret=%d\\n\",name,ret", "GetEnvret=0"], + ["hotspot.jni.GetFieldID", "\"%sfield=%ssig=%s\\n\",name,field,sig", "GetFieldIDfield=myBooleansig=Z"], + ["hotspot.jni.GetFieldID.return", "\"%sret=%d\\n\",name,ret", "GetFieldIDret=[^0]"], + ["hotspot.jni.GetFloatArrayElements", "\"%scp=%d\\n\",name,iscopy", "GetFloatArrayElementscp=0"], + ["hotspot.jni.GetFloatArrayElements.return", "\"%sret=%d\\n\",name,ret", "GetFloatArrayElementsret=[^0]"], + ["hotspot.jni.GetFloatArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "GetFloatArrayRegionstart=0len=5"], + ["hotspot.jni.GetFloatArrayRegion.return", "\"%s\\n\",name", "GetFloatArrayRegion"], + ["hotspot.jni.GetFloatField", "\"%s\\n\",name", "GetFloatField"], + ["hotspot.jni.GetFloatField.return", "\"%s\\n\",name", "GetFloatField"], + ["hotspot.jni.GetIntArrayElements", "\"%scp=%d\\n\",name,iscopy", "GetIntArrayElementscp=0"], + ["hotspot.jni.GetIntArrayElements.return", "\"%sret=%d\\n\",name,ret", "GetIntArrayElementsret=[^0]"], + ["hotspot.jni.GetIntArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "GetIntArrayRegionstart=0len=5"], + ["hotspot.jni.GetIntArrayRegion.return", "\"%s\\n\",name", "GetIntArrayRegion"], + ["hotspot.jni.GetIntField", "\"%s\\n\",name", "GetIntField"], + ["hotspot.jni.GetIntField.return", "\"%sret=%d\\n\",name,ret", "GetIntFieldret=4"], + ["hotspot.jni.GetJavaVM", "\"%s\\n\",name", "GetJavaVM"], + ["hotspot.jni.GetJavaVM.return", "\"%sret=%d\\n\",name,ret", "GetJavaVMret=0"], + ["hotspot.jni.GetLongArrayElements", "\"%scp=%d\\n\",name,iscopy", "GetLongArrayElementscp=0"], + ["hotspot.jni.GetLongArrayElements.return", "\"%sret=%d\\n\",name,ret", "GetLongArrayElementsret=[^0]"], + ["hotspot.jni.GetLongArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "GetLongArrayRegionstart=0len=5"], + ["hotspot.jni.GetLongArrayRegion.return", "\"%s\\n\",name", "GetLongArrayRegion"], + ["hotspot.jni.GetLongField", "\"%s\\n\",name", "GetLongField"], + ["hotspot.jni.GetLongField.return", "\"%sret=%d\\n\",name,ret", "GetLongFieldret=8"], + ["hotspot.jni.GetMethodID", "\"%smethod=%ssig=%s\\n\",name,method,sig", "GetMethodIDmethod=getBooleansig=()Z"], + ["hotspot.jni.GetMethodID.return", "\"%sret=%d\\n\",name,ret", "GetMethodIDret=[^0]"], + ["hotspot.jni.GetObjectArrayElement", "\"%si=%d\\n\",name,index", "GetObjectArrayElementi=1"], + ["hotspot.jni.GetObjectArrayElement.return", "\"%sret=%d\\n\",name,ret", "GetObjectArrayElementret=[^0]"], + ["hotspot.jni.GetObjectClass", "\"%s\\n\",name", "GetObjectClass"], + ["hotspot.jni.GetObjectClass.return", "\"%sret=%d\\n\",name,ret", "GetObjectClassret=[^0]"], + ["hotspot.jni.GetObjectField", "\"%s\\n\",name", "GetObjectField"], + ["hotspot.jni.GetObjectField.return", "\"%sret=%d\\n\",name,ret", "GetObjectFieldret=[^0]"], + ["hotspot.jni.GetObjectRefType", "\"%s\\n\",name", "GetObjectRefType"], + ["hotspot.jni.GetObjectRefType.return", "\"%sret=%d\\n\",name,ret", "GetObjectRefTyperet=2"], + ["hotspot.jni.GetPrimitiveArrayCritical", "\"%s\\n\",name", "GetPrimitiveArrayCritical"], + ["hotspot.jni.GetPrimitiveArrayCritical.return", "\"%sret=%d\\n\",name,ret", "GetPrimitiveArrayCriticalret=[^0]"], + ["hotspot.jni.GetShortArrayElements", "\"%scp=%d\\n\",name,iscopy", "GetShortArrayElementscp=0"], + ["hotspot.jni.GetShortArrayElements.return", "\"%sret=%d\\n\",name,ret", "GetShortArrayElementsret=[^0]"], + ["hotspot.jni.GetShortArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "GetShortArrayRegionstart=0len=5"], + ["hotspot.jni.GetShortArrayRegion.return", "\"%s\\n\",name", "GetShortArrayRegion"], + ["hotspot.jni.GetShortField", "\"%s\\n\",name", "GetShortField"], + ["hotspot.jni.GetShortField.return", "\"%sret=%d\\n\",name,ret", "GetShortFieldret=2"], + ["hotspot.jni.GetStaticBooleanField", "\"%s\\n\",name", "GetStaticBooleanField"], + ["hotspot.jni.GetStaticBooleanField.return", "\"%sret=%d\\n\",name,ret", "GetStaticBooleanFieldret=0"], + ["hotspot.jni.GetStaticByteField", "\"%s\\n\",name", "GetStaticByteField"], + ["hotspot.jni.GetStaticByteField.return", "\"%sret=%d\\n\",name,ret", "GetStaticByteFieldret=1"], + ["hotspot.jni.GetStaticCharField", "\"%s\\n\",name", "GetStaticCharField"], + ["hotspot.jni.GetStaticCharField.return", "\"%sret=%d\\n\",name,ret", "GetStaticCharFieldret=98"], + ["hotspot.jni.GetStaticDoubleField", "\"%s\\n\",name", "GetStaticDoubleField"], + ["hotspot.jni.GetStaticDoubleField.return", "\"%s\\n\",name", "GetStaticDoubleField"], + ["hotspot.jni.GetStaticFieldID", "\"%sfield=%ssig=%s\\n\",name,field,sig", "GetStaticFieldIDfield=myStaticBooleansig=Z"], + ["hotspot.jni.GetStaticFieldID.return", "\"%sret=%d\\n\",name,ret", "GetStaticFieldIDret=[^0]"], + ["hotspot.jni.GetStaticFloatField", "\"%s\\n\",name", "GetStaticFloatField"], + ["hotspot.jni.GetStaticFloatField.return", "\"%s\\n\",name", "GetStaticFloatField"], + ["hotspot.jni.GetStaticIntField", "\"%s\\n\",name", "GetStaticIntField"], + ["hotspot.jni.GetStaticIntField.return", "\"%sret=%d\\n\",name,ret", "GetStaticIntFieldret=32"], + ["hotspot.jni.GetStaticLongField", "\"%s\\n\",name", "GetStaticLongField"], + ["hotspot.jni.GetStaticLongField.return", "\"%sret=%d\\n\",name,ret", "GetStaticLongFieldret=64"], + ["hotspot.jni.GetMethodID", "\"%smethod=%ssig=%s\\n\",name,method,sig", "GetMethodIDmethod=getBooleansig=()Z"], + ["hotspot.jni.GetStaticMethodID.return", "\"%sret=%d\\n\",name,ret", "GetStaticMethodIDret=[^0]"], + ["hotspot.jni.GetStaticObjectField", "\"%s\\n\",name", "GetStaticObjectField"], + ["hotspot.jni.GetStaticObjectField.return", "\"%sret=%d\\n\",name,ret", "GetStaticObjectFieldret=[^0]"], + ["hotspot.jni.GetStaticShortField", "\"%s\\n\",name", "GetStaticShortField"], + ["hotspot.jni.GetStaticShortField.return", "\"%sret=%d\\n\",name,ret", "GetStaticShortFieldret=16"], + ["hotspot.jni.GetStringChars", "\"%scp=%d\\n\",name,iscopy", "GetStringCharscp=0"], + ["hotspot.jni.GetStringChars.return", "\"%sret=%d\\n\",name,ret", "GetStringCharsret=[^0]"], + ["hotspot.jni.GetStringCritical", "\"%scp=%d\\n\",name,iscopy", "GetStringCriticalcp=0"], + ["hotspot.jni.GetStringCritical.return", "\"%sret=%d\\n\",name,ret", "GetStringCriticalret=[^0]"], + ["hotspot.jni.GetStringLength", "\"%s\\n\",name", "GetStringLength"], + ["hotspot.jni.GetStringLength.return", "\"%sret=%d\\n\",name,ret", "GetStringLengthret=4"], + ["hotspot.jni.GetStringRegion", "\"%sst=%dlen=%d\\n\",name,start,len", "GetStringRegionst=1len=2"], + ["hotspot.jni.GetStringRegion.return", "\"%s\\n\",name", "GetStringRegion"], + ["hotspot.jni.GetStringUTFChars", "\"%scp=%d\\n\",name,iscopy", "GetStringUTFCharscp=0"], + ["hotspot.jni.GetStringUTFChars.return", "\"%sret=%s\\n\",name,ret", "GetStringUTFCharsret=WORD"], + ["hotspot.jni.GetStringUTFLength", "\"%s\\n\",name", "GetStringUTFLength"], + ["hotspot.jni.GetStringUTFLength.return", "\"%sret=%d\\n\",name,ret", "GetStringUTFLengthret=6"], + ["hotspot.jni.GetStringUTFRegion", "\"%sst=%dlen=%d\\n\",name,start,len", "GetStringUTFRegionst=1len=2"], + ["hotspot.jni.GetStringUTFRegion.return", "\"%s\\n\",name", "GetStringUTFRegion"], + ["hotspot.jni.GetSuperclass", "\"%s\\n\",name", "GetSuperclass"], + ["hotspot.jni.GetSuperclass.return", "\"%sret=%d\\n\",name,ret", "GetSuperclassret=[^0]"], + ["hotspot.jni.GetVersion", "\"%s\\n\",name", "GetVersion"], + ["hotspot.jni.GetVersion.return", "\"%sret=%x\\n\",name,ret", "GetVersionret=10006"], + ["hotspot.jni.IsAssignableFrom", "\"%s\\n\",name", "IsAssignableFrom"], + ["hotspot.jni.IsAssignableFrom.return", "\"%sret=%d\\n\",name,ret", "IsAssignableFromret=1"], + ["hotspot.jni.IsInstanceOf", "\"%s\\n\",name", "IsInstanceOf"], + ["hotspot.jni.IsInstanceOf.return", "\"%sret=%d\\n\",name,ret", "IsInstanceOfret=1"], + ["hotspot.jni.IsSameObject", "\"%s\\n\",name", "IsSameObject"], + ["hotspot.jni.IsSameObject.return", "\"%sret=%d\\n\",name,ret", "IsSameObjectret=1"], + ["hotspot.jni.MonitorEnter", "\"%s\\n\",name", "MonitorEnter"], + ["hotspot.jni.MonitorEnter.return", "\"%sret=%d\\n\",name,ret", "MonitorEnterret=0"], + ["hotspot.jni.MonitorExit", "\"%s\\n\",name", "MonitorExit"], + ["hotspot.jni.MonitorExit.return", "\"%sret=%d\\n\",name,ret", "MonitorExitret=0"], + ["hotspot.jni.NewBooleanArray", "\"%slen=%d\\n\",name,length", "NewBooleanArraylen=5"], + ["hotspot.jni.NewBooleanArray.return", "\"%sret=%d\\n\",name,ret", "NewBooleanArrayret=[^0]"], + ["hotspot.jni.NewByteArray", "\"%slen=%d\\n\",name,length", "NewByteArraylen=5"], + ["hotspot.jni.NewByteArray.return", "\"%sret=%d\\n\",name,ret", "NewByteArrayret=[^0]"], + ["hotspot.jni.NewCharArray", "\"%slen=%d\\n\",name,length", "NewCharArraylen=5"], + ["hotspot.jni.NewCharArray.return", "\"%sret=%d\\n\",name,ret", "NewCharArrayret=[^0]"], + ["hotspot.jni.NewDirectByteBuffer", "\"%ssize=%d\\n\",name,size", "NewDirectByteBuffersize=128"], + ["hotspot.jni.NewDirectByteBuffer.return", "\"%sret=%d\\n\",name,ret", "NewDirectByteBufferret=[^0]"], + ["hotspot.jni.NewDoubleArray", "\"%slen=%d\\n\",name,length", "NewDoubleArraylen=5"], + ["hotspot.jni.NewDoubleArray.return", "\"%sret=%d\\n\",name,ret", "NewDoubleArrayret=[^0]"], + ["hotspot.jni.NewFloatArray", "\"%slen=%d\\n\",name,length", "NewFloatArraylen=5"], + ["hotspot.jni.NewFloatArray.return", "\"%sret=%d\\n\",name,ret", "NewFloatArrayret=[^0]"], + ["hotspot.jni.NewGlobalRef", "\"%s\\n\",name", "NewGlobalRef"], + ["hotspot.jni.NewGlobalRef.return", "\"%sret=%d\\n\",name,ret", "NewGlobalRefret=[^0]"], + ["hotspot.jni.NewIntArray", "\"%slen=%d\\n\",name,length", "NewIntArraylen=5"], + ["hotspot.jni.NewIntArray.return", "\"%sret=%d\\n\",name,ret", "NewIntArrayret=[^0]"], + ["hotspot.jni.NewLocalRef", "\"%s\\n\",name", "NewLocalRef"], + ["hotspot.jni.NewLocalRef.return", "\"%sret=%d\\n\",name,ret", "NewLocalRefret=[^0]"], + ["hotspot.jni.NewLongArray", "\"%slen=%d\\n\",name,length", "NewLongArraylen=5"], + ["hotspot.jni.NewLongArray.return", "\"%sret=%d\\n\",name,ret", "NewLongArrayret=[^0]"], + ["hotspot.jni.NewObjectA", "\"%s\\n\",name", "NewObjectA"], + ["hotspot.jni.NewObjectA.return", "\"%sret=%d\\n\",name,ret", "NewObjectAret=0"], + ["hotspot.jni.NewObjectArray", "\"%slen=%dinit=%d\\n\",name,length,initial", "NewObjectArraylen=5init=0"], + ["hotspot.jni.NewObjectArray.return", "\"%sret=%d\\n\",name,ret", "NewObjectArrayret=[^0]"], + ["hotspot.jni.NewObject", "\"%s\\n\",name", "NewObject"], + ["hotspot.jni.NewObject.return", "\"%sret=%d\\n\",name,ret", "NewObjectret=[^0]"], + ["hotspot.jni.NewObjectV", "\"%s\\n\",name", "NewObjectV"], + ["hotspot.jni.NewObjectV.return", "\"%sret=%d\\n\",name,ret", "NewObjectVret=[^0]"], + ["hotspot.jni.NewShortArray", "\"%slen=%d\\n\",name,length", "NewShortArraylen=5"], + ["hotspot.jni.NewShortArray.return", "\"%sret=%d\\n\",name,ret", "NewShortArrayret=[^0]"], + ["hotspot.jni.NewString", "\"%slen=%d\\n\",name,len", "NewStringlen=4"], + ["hotspot.jni.NewString.return", "\"%sret=%d\\n\",name,ret", "NewStringret=[^0]"], + ["hotspot.jni.NewStringUTF", "\"%sbytes=%s\\n\",name,bytes", "NewStringUTFbytes=WORD"], + ["hotspot.jni.NewStringUTF.return", "\"%sret=%d\\n\",name,ret", "NewStringUTFret=[^0]"], + ["hotspot.jni.NewWeakGlobalRef", "\"%s\\n\",name", "NewWeakGlobalRef"], + ["hotspot.jni.NewWeakGlobalRef.return", "\"%sret=%d\\n\",name,ret", "NewWeakGlobalRefret=[^0]"], + ["hotspot.jni.PopLocalFrame", "\"%s\\n\",name", "PopLocalFrame"], + ["hotspot.jni.PopLocalFrame.return", "\"%sret=%d\\n\",name,ret", "PopLocalFrameret=0"], + ["hotspot.jni.PushLocalFrame", "\"%scap=%d\\n\",name,capacity", "PushLocalFramecap=10"], + ["hotspot.jni.PushLocalFrame.return", "\"%sret=%d\\n\",name,ret", "PushLocalFrameret=0"], + ["hotspot.jni.RegisterNatives", "\"%s\\n\",name", "RegisterNatives"], + ["hotspot.jni.RegisterNatives.return", "\"%sret=%d\\n\",name,ret", "RegisterNativesret=0"], + ["hotspot.jni.ReleaseBooleanArrayElements", "\"%smode=%d\\n\",name,mode", "ReleaseBooleanArrayElementsmode=2"], + ["hotspot.jni.ReleaseBooleanArrayElements.return", "\"%s\\n\",name", "ReleaseBooleanArrayElements"], + ["hotspot.jni.ReleaseByteArrayElements", "\"%smode=%d\\n\",name,mode", "ReleaseByteArrayElementsmode=2"], + ["hotspot.jni.ReleaseByteArrayElements.return", "\"%s\\n\",name", "ReleaseByteArrayElements"], + ["hotspot.jni.ReleaseCharArrayElements", "\"%smode=%d\\n\",name,mode", "ReleaseCharArrayElementsmode=2"], + ["hotspot.jni.ReleaseCharArrayElements.return", "\"%s\\n\",name", "ReleaseCharArrayElements"], + ["hotspot.jni.ReleaseDoubleArrayElements", "\"%smode=%d\\n\",name,mode", "ReleaseDoubleArrayElementsmode=2"], + ["hotspot.jni.ReleaseDoubleArrayElements.return", "\"%s\\n\",name", "ReleaseDoubleArrayElements"], + ["hotspot.jni.ReleaseFloatArrayElements", "\"%smode=%d\\n\",name,mode", "ReleaseFloatArrayElementsmode=2"], + ["hotspot.jni.ReleaseFloatArrayElements.return", "\"%s\\n\",name", "ReleaseFloatArrayElements"], + ["hotspot.jni.ReleaseIntArrayElements", "\"%smode=%d\\n\",name,mode", "ReleaseIntArrayElementsmode=2"], + ["hotspot.jni.ReleaseIntArrayElements.return", "\"%s\\n\",name", "ReleaseIntArrayElements"], + ["hotspot.jni.ReleaseLongArrayElements", "\"%smode=%d\\n\",name,mode", "ReleaseLongArrayElementsmode=2"], + ["hotspot.jni.ReleaseLongArrayElements.return", "\"%s\\n\",name", "ReleaseLongArrayElements"], + ["hotspot.jni.ReleasePrimitiveArrayCritical", "\"%smode=%d\\n\",name,mode", "ReleasePrimitiveArrayCriticalmode=2"], + ["hotspot.jni.ReleasePrimitiveArrayCritical.return", "\"%s\\n\",name", "ReleasePrimitiveArrayCritical"], + ["hotspot.jni.ReleaseShortArrayElements", "\"%smode=%d\\n\",name,mode", "ReleaseShortArrayElementsmode=2"], + ["hotspot.jni.ReleaseShortArrayElements.return", "\"%s\\n\",name", "ReleaseShortArrayElements"], + ["hotspot.jni.ReleaseStringChars", "\"%s\\n\",name", "ReleaseStringChars"], + ["hotspot.jni.ReleaseStringChars.return", "\"%s\\n\",name", "ReleaseStringChars"], + ["hotspot.jni.ReleaseStringCritical", "\"%s\\n\",name", "ReleaseStringCritical"], + ["hotspot.jni.ReleaseStringCritical.return", "\"%s\\n\",name", "ReleaseStringCritical"], + ["hotspot.jni.ReleaseStringUTFChars", "\"%sutf=%s\\n\",name,utf", "ReleaseStringUTFCharsutf=WORD"], + ["hotspot.jni.ReleaseStringUTFChars.return", "\"%s\\n\",name", "ReleaseStringUTFChars"], + ["hotspot.jni.SetBooleanArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "SetBooleanArrayRegionstart=0len=5"], + ["hotspot.jni.SetBooleanArrayRegion.return", "\"%s\\n\",name", "SetBooleanArrayRegion"], + ["hotspot.jni.SetBooleanField", "\"%sval=%d\\n\",name,value", "SetBooleanFieldval=1"], + ["hotspot.jni.SetBooleanField.return", "\"%s\\n\",name", "SetBooleanField"], + ["hotspot.jni.SetByteArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "SetByteArrayRegionstart=0len=5"], + ["hotspot.jni.SetByteArrayRegion.return", "\"%s\\n\",name", "SetByteArrayRegion"], + ["hotspot.jni.SetByteField", "\"%sval=%d\\n\",name,value", "SetByteFieldval=2"], + ["hotspot.jni.SetByteField.return", "\"%s\\n\",name", "SetByteField"], + ["hotspot.jni.SetCharArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "SetCharArrayRegionstart=0len=5"], + ["hotspot.jni.SetCharArrayRegion.return", "\"%s\\n\",name", "SetCharArrayRegion"], + ["hotspot.jni.SetCharField", "\"%sval=%d\\n\",name,value", "SetCharFieldval=65"], + ["hotspot.jni.SetCharField.return", "\"%s\\n\",name", "SetCharField"], + ["hotspot.jni.SetDoubleArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "SetDoubleArrayRegionstart=0len=5"], + ["hotspot.jni.SetDoubleArrayRegion.return", "\"%s\\n\",name", "SetDoubleArrayRegion"], + ["hotspot.jni.SetDoubleField", "\"%s\\n\",name", "SetDoubleField"], + ["hotspot.jni.SetDoubleField.return", "\"%s\\n\",name", "SetDoubleField"], + ["hotspot.jni.SetFloatArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "SetFloatArrayRegionstart=0len=5"], + ["hotspot.jni.SetFloatArrayRegion.return", "\"%s\\n\",name", "SetFloatArrayRegion"], + ["hotspot.jni.SetFloatField", "\"%s\\n\",name", "SetFloatField"], + ["hotspot.jni.SetFloatField.return", "\"%s\\n\",name", "SetFloatField"], + ["hotspot.jni.SetIntArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "SetIntArrayRegionstart=0len=5"], + ["hotspot.jni.SetIntArrayRegion.return", "\"%s\\n\",name", "SetIntArrayRegion"], + ["hotspot.jni.SetIntField", "\"%sval=%d\\n\",name,value", "SetIntFieldval=7"], + ["hotspot.jni.SetIntField.return", "\"%s\\n\",name", "SetIntField"], + ["hotspot.jni.SetLongArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "SetLongArrayRegionstart=0len=5"], + ["hotspot.jni.SetLongArrayRegion.return", "\"%s\\n\",name", "SetLongArrayRegion"], + ["hotspot.jni.SetLongField", "\"%sval=%d\\n\",name,value", "SetLongFieldval=13"], + ["hotspot.jni.SetLongField.return", "\"%s\\n\",name", "SetLongField"], + ["hotspot.jni.SetObjectArrayElement", "\"%s\\n\",name", "SetObjectArrayElement"], + ["hotspot.jni.SetObjectArrayElement.return", "\"%s\\n\",name", "SetObjectArrayElement"], + ["hotspot.jni.SetObjectField", "\"%s\\n\",name", "SetObjectField"], + ["hotspot.jni.SetObjectField.return", "\"%s\\n\",name", "SetObjectField"], + ["hotspot.jni.SetShortArrayRegion", "\"%sstart=%dlen=%d\\n\",name,start,len", "SetShortArrayRegionstart=0len=5"], + ["hotspot.jni.SetShortArrayRegion.return", "\"%s\\n\",name", "SetShortArrayRegion"], + ["hotspot.jni.SetShortField", "\"%sval=%d\\n\",name,value", "SetShortFieldval=11"], + ["hotspot.jni.SetShortField.return", "\"%s\\n\",name", "SetShortField"], + ["hotspot.jni.SetStaticBooleanField", "\"%sval=%d\\n\",name,value", "SetStaticBooleanFieldval=1"], + ["hotspot.jni.SetStaticBooleanField.return", "\"%s\\n\",name", "SetStaticBooleanField"], + ["hotspot.jni.SetStaticByteField", "\"%sval=%d\\n\",name,value", "SetStaticByteFieldval=2"], + ["hotspot.jni.SetStaticByteField.return", "\"%s\\n\",name", "SetStaticByteField"], + ["hotspot.jni.SetStaticCharField", "\"%sval=%d\\n\",name,value", "SetStaticCharFieldval=65"], + ["hotspot.jni.SetStaticCharField.return", "\"%s\\n\",name", "SetStaticCharField"], + ["hotspot.jni.SetStaticDoubleField", "\"%s\\n\",name", "SetStaticDoubleField"], + ["hotspot.jni.SetStaticDoubleField.return", "\"%s\\n\",name", "SetStaticDoubleField"], + ["hotspot.jni.SetStaticFloatField", "\"%s\\n\",name", "SetStaticFloatField"], + ["hotspot.jni.SetStaticFloatField.return", "\"%s\\n\",name", "SetStaticFloatField"], + ["hotspot.jni.SetStaticIntField", "\"%sval=%d\\n\",name,value", "SetStaticIntFieldval=7"], + ["hotspot.jni.SetStaticIntField.return", "\"%s\\n\",name", "SetStaticIntField"], + ["hotspot.jni.SetStaticLongField", "\"%sval=%d\\n\",name,value", "SetStaticLongFieldval=13"], + ["hotspot.jni.SetStaticLongField.return", "\"%s\\n\",name", "SetStaticLongField"], + ["hotspot.jni.SetStaticObjectField", "\"%s\\n\",name", "SetStaticObjectField"], + ["hotspot.jni.SetStaticObjectField.return", "\"%s\\n\",name", "SetStaticObjectField"], + ["hotspot.jni.SetStaticShortField", "\"%sval=%d\\n\",name,value", "SetStaticShortFieldval=11"], + ["hotspot.jni.SetStaticShortField.return", "\"%s\\n\",name", "SetStaticShortField"], + ["hotspot.jni.Throw", "\"%s\\n\",name", "Throw"], + ["hotspot.jni.Throw.return", "\"%sret=%d\\n\",name,ret", "Throwret=0"], + ["hotspot.jni.ThrowNew", "\"%smsg=%s\\n\",name,msg", "ThrowNewmsg=This exception is for testing purposes only."], + ["hotspot.jni.ThrowNew.return", "\"%sret=%d\\n\",name,ret", "ThrowNewret=0"], + ["hotspot.jni.ToReflectedField", "\"%s\\n\",name", "ToReflectedField"], + ["hotspot.jni.ToReflectedField.return", "\"%sret=%d\\n\",name,ret", "ToReflectedFieldret=[^0]"], + ["hotspot.jni.ToReflectedMethod", "\"%s\\n\",name", "ToReflectedMethod"], + ["hotspot.jni.ToReflectedMethod.return", "\"%sret=%d\\n\",name,ret", "ToReflectedMethodret=[^0]"], + ["hotspot.jni.UnregisterNatives", "\"%s\\n\",name", "UnregisterNatives"], + ["hotspot.jni.UnregisterNatives.return", "\"%sret=%d\\n\",name,ret", "UnregisterNativesret=0"]); + +# To test for known probe prefix. Determines main type of test run. +my $hs_regex = "^hotspot\."; +my $jni_regex = "^hotspot\.jni\."; + +# Status of test run. +my $working_count = 0; +my $undetected_count = 0; +my $broken_count = 0; + +# Stuffed based on argument(s), used as argument to stap executable. +my @tapset_dirs = (); + +# Set based on arguments, used to during compilation and/or running of tests. +my $ignore_system_tapset = ""; +my $java_exec = ""; +my $javac_exec = ""; +my $jvm_dir = ""; +my $jvm_so = ""; +my $test_sourcedir = "."; +my @include_dirs = (); + + +### MAIN BODY +# Short and sweet. +process_args(); +log_preamble(); +build_tests(); +my @detected_probes = detect_probes(@probestrings); +if (can_run_probes()) { + test_probes(@detected_probes); +} +summarize(); +log_postamble(); +clean_up(); +exit($broken_count | $undetected_count); + +### PRIMARY SUBROUTINES +# These are called by the main body of the script. + +# Uses Getopt::Std::getopts() to grab user arguments, then performs further +# processing to ensure valid combination of args and set several variables +# based on args. +sub process_args { + die "Try \"jstaptest.pl --help\" for usage information.\n" + if (!getopts('B:A:J:o:a:S:') || ($opt_o && $opt_a)); + # -o and -a are mutually exclusive. + if ($opt_B && $opt_A) { + die "Directory $opt_B not found." unless (-d $opt_B); + die "Directory $opt_B/j2sdk-image/tapset not found.\nTry rebuilding Icedtea with systemtap support.\n" + unless (-d "$opt_B/j2sdk-image/tapset"); + push(@tapset_dirs, "-I$opt_B/j2sdk-image/tapset"); + set_java_vars("$opt_B/j2sdk-image", $opt_A); + $ignore_system_tapset = "SYSTEMTAP_TAPSET=\"\""; + } + elsif ($opt_J) { + set_java_vars($opt_J, get_arch_dir()); + + } + else { + die "Try \"./jstaptest.pl --help\" for usage information.\n"; + } + + if ($opt_S) { + die "Directory $opt_S not found." unless (-d $opt_S); + $test_sourcedir = "$opt_S"; + } + + if ($opt_o) { + $logfile_name = $opt_o; + mkpath(dirname($opt_o)) or + die "Couldn't make enclosing directory for $opt_o\n$!" + unless (-d dirname($opt_o)); + open($log_file, '>', $opt_o) or + die "Couldn't open log file: $opt_a\n$!"; + } + if ($opt_a) { + $logfile_name = $opt_a; + mkpath(dirname($opt_a)) or + die "Couldn't make enclosing directory for $opt_a\n$!" + unless (-d dirname($opt_a)); + open($log_file, '>>', $opt_a) or + die "Couldn't open log file: $opt_a\n$!"; + } +} + +# Any text that should precede a test run in the log file goes here. +sub log_preamble { + just_log("###############################################################"); + just_log("Start of test run.\n" . gmtime()); +} + +# Tests consist of a number of C and Java files. These need to be compiled. +sub build_tests { + log_and_print("Compiling tests."); + my $compile_command = "$javac_exec -d ./ $test_sourcedir/*.java"; + just_log($compile_command); + system($compile_command); + if ($? != 0) { + log_and_print("Error compiling one or more .java files."); + clean_up(); + die "Cannot compile tests.\n"; + } + $compile_command = "gcc " . join(' ', @include_dirs) . + " -c -fPIC $test_sourcedir/JNITestClass.c -o JNITestClass.o"; + just_log($compile_command); + system($compile_command); + if ($? != 0) { + log_and_print("Error compiling JNITestClass.o"); + clean_up(); + die "Cannot compile tests.\n"; + } + $compile_command = "gcc -shared -o libJNITestClass.so -fPIC JNITestClass.o"; + just_log($compile_command); + system($compile_command); + if ($? != 0) { + log_and_print("Error building libJNITestClass.so"); + clean_up(); + die "Cannot compile tests.\n"; + } + $compile_command = "gcc " . join(' ', @include_dirs) . + " -pthread -L$jvm_dir -L. -lJNITestClass $jvm_so" . + " -o JNIStapTest $test_sourcedir/JNIStapTest.c"; + just_log($compile_command); + system($compile_command); + if ($? != 0) { + log_and_print("Error compiling JNIStapTest"); + clean_up(); + die "Cannot compile tests.\n"; + } +} + +# Filter out the list of probes. If Systemtap cannot locate a probe using the +# -l argument, it makes little sense to try to run a script based on it. +# This also means we can detect this case as a distinct failure mode. +sub detect_probes { + log_and_print("Testing if systemtap can match probes."); + my @probes_detected = (); + my ($probe_name, $probe_printargs, $probe_output, $stap_pre, $stap_command, + @sysargs); + $stap_pre = "$ignore_system_tapset stap " . join(' ', @tapset_dirs); + foreach my $probe_index (0..$#_) { + $probe_name = $_[$probe_index][0]; + $probe_printargs = $_[$probe_index][1]; + $probe_output = $_[$probe_index][2]; + $stap_command = "$stap_pre -L $probe_name 2>&1 | grep -q \"^$probe_name\""; + just_log($stap_command); + print("."); + system($stap_command); + if ($? != 0) { + print("\n"); + log_and_print("Probe $probe_name not found."); + $undetected_count++; + } + else { + just_log("Probe $probe_name found."); + push(@probes_detected, [$probe_name, $probe_printargs, + $probe_output]); + } + } + print("\n"); + return @probes_detected; +} + +# Check whether we can run stap while probing. +# This needs extra user privs. If not, we only run the detect_probes() +# test, but not the test_probes() test. +sub can_run_probes { + log_and_print("Check whether we have enough privs to run systemtap script..."); + my $stap_command = "stap -e 'probe begin { log(\"Hello World\"); exit(); }'"; + just_log($stap_command); + my $result = `$stap_command 2>&1`; + if ($? != 0) { + # First few error lines give a hint... + print(join("\n", (split /\n/, $result)[0..5]), "\n"); + just_log($result); + log_and_print("Cannot run simple stap script, skipping probe tests."); + return 0; + } + print("OK\n"); + return 1; +} + +# For each probe, run a stap script using the -c command to have it load +# and unload automatically around the execution of a single command. This +# command will be the running of a java program (in the case of probes +# from the hotspot.stp tapset) or a C program which uses the JNI +# Invocation API (in the case of probes from the hotspot_jni.stp tapset), +# which is designed to trigger the named probe in as minimal of a test +# case as possible. Associated with each probe is a format string (with +# variables) that is called in a printf statement within the stap script, +# and a regex designed to resemble the expected output of said printf +# statement. +sub test_probes { + log_and_print("Testing if detected probes work as expected. This may take a while..."); + my ($probe_name, $probe_suffix, $probe_printargs, $probe_output, + $stap_pre, $stap_command, $jvm_xxarg); + $stap_pre = "stap " . join(' ', @tapset_dirs); + foreach my $probe_index (0..$#_) { + $jvm_xxarg = ""; + $probe_name = $_[$probe_index][0]; + $probe_suffix = $probe_name; + $probe_printargs = $_[$probe_index][1]; + $probe_output = $_[$probe_index][2]; + $stap_command = "$stap_pre -e 'probe $probe_name { printf($probe_printargs) }' -c"; + if ($probe_name =~ m/($jni_regex)/) { + # JNI probes are triggered by calling a C program which uses the + # invocation API on which the probes are based. + $probe_suffix =~ s/($jni_regex)//; + # The test against the jni function entry and return probes are + # identical. + $probe_suffix =~ s/\.return$//; + $stap_command = "$stap_command 'export LD_LIBRARY_PATH=.:$jvm_dir && ./JNIStapTest $probe_suffix'"; + if ($probe_suffix =~ m/^FatalError$/) { + # This test intentionally crashes the JVM, generating output + # on stderr. We don't want to see this noise. + $stap_command = "$stap_command 2>&1"; + } + } + elsif ($probe_name =~ m/($hs_regex)/) { + # Hotspot probes are triggered by calling a Java program which sets + # up appropriate conditions in the JVM to hit the probe points. + $probe_suffix =~ s/($hs_regex)//; + # Some probes are optimized out in the default JVM configuration, so + # we need some special arguments. + if ($probe_suffix =~ m/^monitor/) { + $jvm_xxarg = "-XX:+DTraceMonitorProbes"; + } + elsif ($probe_suffix =~ m/^method_(entry|return)$/) { + $jvm_xxarg = "-XX:+DTraceMethodProbes"; + } + elsif ($probe_suffix =~ m/^object_alloc$/) { + $jvm_xxarg = "-XX:+DTraceAllocProbes"; + } + elsif ($probe_suffix =~ m/^(method_compile|compiled_method)/) { + # Default here is much larger, this way our test doesn't need to + # run as long. + $jvm_xxarg = "-XX:CompileThreshold=100"; + } + $stap_command = "$stap_command '$java_exec $jvm_xxarg staptest.SystemtapTester $probe_suffix'"; + } + else { + just_log("Probe $probe_name has no test defined."); + $broken_count++; + next; + } + $stap_command = "$stap_command | grep \"$probe_output\" 2>&1 >> /dev/null"; + print("."); + just_log($stap_command); + system($stap_command); + if ($? == 0) { + just_log("Probe $probe_name working."); + $working_count++; + } + else { + print("\n"); + log_and_print("Probe $probe_name failed."); + $broken_count++; + } + } + print("\n"); +} + +# Output a tally of test results. +sub summarize { + if ($working_count) { + log_and_print("Working probes: $working_count"); + } + if ($broken_count) { + log_and_print("Broken probes: $broken_count"); + } + if ($undetected_count) { + log_and_print("Undetected probes: $undetected_count"); + } + +} + +# Any text that should follow a test run in the log file goes here. +sub log_postamble { + if ($broken_count | $undetected_count) { + log_and_print("Some tests did not work as expected. See file " . + $logfile_name . " for details."); + } + just_log("End of test run"); +} + +# Remove compiled files and close file handle(s). Any other cleanup needed +# should be added here. +sub clean_up { + log_and_print("Removing compiled test files."); + rmtree('staptest'); + unlink <*.o>; + unlink <*.so>; + unlink "JNIStapTest"; + if ($log_file) { + close($log_file); + } +} + + +# HELPER SUBROUTINES +# Subroutines other than top-level. + +# Used when processing arguments to set a number of variables that refer to +# files/directories within $JAVA_HOME. +sub set_java_vars { + my ($_java_home, $_arch_dir) = @_; + $java_exec = "$_java_home/jre/bin/java"; + $javac_exec = "$_java_home/bin/javac"; + $jvm_dir = "$_java_home/jre/lib/$_arch_dir/server"; + $jvm_so = "$jvm_dir/libjvm.so"; + push(@include_dirs, "-I$_java_home/include"); + push(@include_dirs, "-I$_java_home/include/linux"); + die "Java executable not found: $java_exec\n" unless (-x $java_exec); + die "Javac executable not found: $javac_exec\n" unless (-x $javac_exec); + die "Directory not found: $jvm_dir\n" unless (-d $jvm_dir); + die "File not found: $jvm_so\n" unless (-r $jvm_so); + die "jni.h or jni_md.h headers not found within directory: $_java_home/j2sdk-image/include" + unless ((-r "$_java_home/include/jni.h") && + (-r "$_java_home/include/linux/jni_md.h")); +} + +# When testing against an installed jdk, we need to know the current +# architecture to find libjvm.so within the jdk directory tree. +sub get_arch_dir { + my $sys_arch = $Config{archname}; + if ($sys_arch =~ m/x86_64/) { + return "amd64"; + } + elsif ($sys_arch =~ m/i.86/) { + return "i586"; + } + elsif ($sys_arch =~ m/alpha/) { + return "alpha"; + } + elsif ($sys_arch =~ m/arm/) { + return "arm"; + } + elsif ($sys_arch =~ m/mips-/) { + return "mips"; + } + elsif ($sys_arch =~ m/mipsel/) { + return "mipsel"; + } + elsif ($sys_arch =~ m/powerpc-/) { + return "ppc"; + } + elsif ($sys_arch =~ m/powerpc64/) { + return "ppc64"; + } + elsif ($sys_arch =~ m/sparc64/) { + return "sparcv9"; + } + elsif ($sys_arch =~ m/s390/) { + return "s390"; + } + else { + die "Unknown arch: $sys_arch\n"; + } +} + +# If we are logging, send arguments as lines to log file. +sub just_log { + if ($log_file) { + foreach my $line (@_) { + print $log_file "$line\n"; + } + } +} + +# This is sort of like a "tee $logfile". +sub log_and_print { + just_log(@_); + foreach my $line (@_) { + print("$line\n"); + } +} + + +# OVERRIDDEN FUNCTIONS + +# Runs when --help option is passed, thanks to hooks in Getopt::Std::getopts(); +sub main::HELP_MESSAGE { + print("\n"); + print("To run test suite:\n"); + print("\n"); + print(" $ ./jstaptest.sh [[--help] | [<[-B <DIR> -A <ARCH>] | [-J <DIR>]> [-S <DIR>] [-<o|a> <LOGFILE>]]]\n"); + print("\n"); + print("--help will display this help message.\n"); + print("\n"); + print("\n"); + print("One of -BA or -J *must* be used.\n"); + print("\n"); + print("-J can be used to specify the location of the icedtea install on\n"); + print(" the system. Specifically, this directory should contain the\n"); + print(" directories bin, jre, lib, and include. Only the tapsets in\n"); + print(" systemtap's default directory will be tested. Arch-specific\n"); + print(" directories will be determined from the system's arch.\n"); + print("\n"); + print("\n"); + print("-BA can be used to specify a local icedtea build.\n"); + print(" -B should be equivalent to the \$(BUILD_OUTPUT_DIR) in the\n"); + print(" icedtea Makefile.\n"); + print(" For example:\n"); + print(" ./jstaptest.sh -B \\\n"); + print(" /path/to/icedtea6/openjdk/build/<OS-ARCH>/\n"); + print("\n"); + print(" -A must also be used when -B is used, to specify the \n"); + print(" architecture of the icedtea build, \$(BUILD_ARCH_DIR) from\n"); + print(" the icedtea Makefile.\n"); + print("\n"); + print("\n"); + print("-S can be used to specify the directory where the test source\n"); + print(" code can be found. If it is omitted, the current working\n"); + print(" directory is assumed.\n"); + print("\n"); + print("\n"); + print("-o or -a specify a log file for more detailed output.\n"); + print(" Using -o will replace the existing file if present, while -a\n"); + print(" will append. These two options are mutually exclusive. The\n"); + print(" log file will contain specifics of which probes pass, fail,\n"); + print(" or are not detected by systemtap, along with a record of\n"); + print(" the arguments passed to the script and the command executed\n"); + print(" for each test\n"); + print("\n"); +} + +####################################################################### +