changeset 2527:d4b7c0a97901

PR2256: Add tapset tests. 2015-03-04 Andrew John Hughes <gnu.andrew@member.fsf.org> * Makefile.am: (clean-tests): Add dependency on clean-jtreg-reports. (clean-local): Drop clean-jtreg-reports. * NEWS: Updated. 2012-03-23 Jon VanAlten <jon.vanalten@redhat.com> * Makefile.am: (check-local): Depend on check-tapset. (clean-tests): New target to group test cleanup rules. (clean-local): Depend on clean-tests rather than clean-jtreg. (.PHONY): Add clean-tests and clean-tapset-report. (check-tapset): Add target to run tapset tests. (clean-tapset-report): Cleanup tapset test output. * 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 Andrew John Hughes <gnu_andrew@member.fsf.org>
date Wed, 04 Mar 2015 15:00:16 +0000
parents a9271fe74b8d
children b833c6a3aa60
files ChangeLog Makefile.am NEWS 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 15 files changed, 3728 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Mar 03 00:15:26 2015 +0000
+++ b/ChangeLog	Wed Mar 04 15:00:16 2015 +0000
@@ -1,3 +1,47 @@
+2015-03-04  Andrew John Hughes  <gnu.andrew@member.fsf.org>
+
+	* Makefile.am:
+	(clean-tests): Add dependency on clean-jtreg-reports.
+	(clean-local): Drop clean-jtreg-reports.
+	* NEWS: Updated.
+
+2012-03-23  Jon VanAlten  <jon.vanalten@redhat.com>
+
+	* Makefile.am:
+	(check-local): Depend on check-tapset.
+	(clean-tests): New target to group test cleanup
+	rules.
+	(clean-local): Depend on clean-tests rather than
+	clean-jtreg.
+	(.PHONY): Add clean-tests and clean-tapset-report.
+	(check-tapset): Add target to run tapset tests.
+	(clean-tapset-report): Cleanup tapset test output.
+	* 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.
+
 2015-03-02  Andrew John Hughes  <gnu.andrew@member.fsf.org>
 
 	* Makefile.am:
--- a/Makefile.am	Tue Mar 03 00:15:26 2015 +0000
+++ b/Makefile.am	Wed Mar 04 15:00:16 2015 +0000
@@ -495,9 +495,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 clean-jtreg-reports
+	if [ $(abs_top_srcdir) != $(abs_top_builddir) ] ; then \
+	  if [ -e test ] ; then \
+	    rmdir test ; \
+	  fi \
+	fi
+
+clean-local: clean-tests clean-pulse-java \
  clean-icedtea clean-icedtea-debug 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 \
@@ -534,7 +541,8 @@
 	clean-jamvm clean-extract-jamvm clean-add-jamvm clean-add-jamvm-debug \
 	clean-extract-hotspot clean-sanitise-openjdk clean-icedtea-debug \
 	clean-download-nashorn clean-extract-nashorn clean-download-hotspot \
-	clean-add-archive clean-add-archive-debug clean-add-archive-boot
+	clean-add-archive clean-add-archive-debug clean-add-archive-boot \
+	clean-tests clean-tapset-report
 
 env:
 	@echo 'unset JAVA_HOME'
@@ -2173,6 +2181,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/NEWS	Tue Mar 03 00:15:26 2015 +0000
+++ b/NEWS	Wed Mar 04 15:00:16 2015 +0000
@@ -54,6 +54,7 @@
   - PR2212: DGifCloseFile call should check the return value, not the error code, for failure
   - PR2227: giflib 5.1 conditional excludes 6.0, 7.0, etc.
   - PR2248: HotSpot tarball fails verification after download
+  - PR2256: Add SystemTap tests
   - Don't substitute 'j' for '-j' inside -I directives
   - Extend 8041658 to all files in the HotSpot build.
   - Remove jcheck
--- a/tapset/hotspot_jni.stp.in	Tue Mar 03 00:15:26 2015 +0000
+++ b/tapset/hotspot_jni.stp.in	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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	Wed Mar 04 15:00:16 2015 +0000
@@ -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");
+}
+
+#######################################################################
+