| /* |
| * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include "jni_tools.h" |
| #include "agent_common.h" |
| #include "jvmti_tools.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* The test adds all capabilities suitable for profiling at OnLoad phase: |
| * |
| * can_tag_objects |
| * can_get_owned_monitor_info |
| * can_get_current_contended_monitor |
| * can_get_monitor_info |
| * can_maintain_original_method_order |
| * can_get_current_thread_cpu_time |
| * can_get_thread_cpu_time |
| * can_generate_all_class_hook_events |
| * can_generate_compiled_method_load_events |
| * can_generate_monitor_events |
| * can_generate_vm_object_alloc_events |
| * can_generate_native_method_bind_events |
| * can_generate_garbage_collection_events |
| * can_generate_object_free_events |
| * |
| * and sets calbacks and enables events correspondent to capabilities above. |
| * Then checks that GetCapabilities returns correct list of possessed |
| * capabilities in Live phase, and checks that correspondent possessed |
| * functions works and requested events are generated. |
| */ |
| |
| /* ========================================================================== */ |
| |
| /* scaffold objects */ |
| static jlong timeout = 0; |
| |
| /* test objects */ |
| static jthread thread = NULL; |
| static jclass klass = NULL; |
| |
| /* event counts */ |
| static int ClassFileLoadHookEventsCount = 0; |
| static int CompiledMethodLoadEventsCount = 0; |
| static int CompiledMethodUnloadEventsCount = 0; |
| static int MonitorContendedEnterEventsCount = 0; |
| static int MonitorContendedEnteredEventsCount = 0; |
| static int MonitorWaitEventsCount = 0; |
| static int MonitorWaitedEventsCount = 0; |
| static int VMObjectAllocEventsCount = 0; |
| static int NativeMethodBindEventsCount = 0; |
| static int GarbageCollectionStartEventsCount = 0; |
| static int GarbageCollectionFinishEventsCount = 0; |
| static int ObjectFreeEventsCount = 0; |
| |
| /* ========================================================================== */ |
| |
| /** callback functions **/ |
| |
| static void JNICALL |
| ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *jni_env, |
| jclass class_beeing_redefined, jobject loader, |
| const char* name, jobject protection_domain, |
| jint class_data_len, const unsigned char* class_data, |
| jint *new_class_data_len, unsigned char** new_class_data) { |
| |
| ClassFileLoadHookEventsCount++; |
| NSK_DISPLAY1("ClassFileLoadHook event: %s\n", name); |
| } |
| |
| static void JNICALL |
| CompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, |
| jint code_size, const void* code_addr, jint map_length, |
| const jvmtiAddrLocationMap* map, const void* compile_info) { |
| char *name = NULL; |
| char *signature = NULL; |
| |
| CompiledMethodLoadEventsCount++; |
| |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB5(GetMethodName, |
| jvmti_env, method, &name, &signature, NULL))) { |
| nsk_jvmti_setFailStatus(); |
| return; |
| } |
| NSK_DISPLAY3("CompiledMethodLoad event: %s%s (0x%p)\n", |
| name, signature, code_addr); |
| if (name != NULL) |
| NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)name); |
| if (signature != NULL) |
| NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)signature); |
| } |
| |
| static void JNICALL |
| CompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method, |
| const void* code_addr) { |
| char *name = NULL; |
| char *sig = NULL; |
| jvmtiError err; |
| CompiledMethodUnloadEventsCount++; |
| |
| NSK_DISPLAY0("CompiledMethodUnload event received\n"); |
| // Check for the case that the class has been unloaded |
| err = (*jvmti_env)->GetMethodName(jvmti_env, method, &name, &sig, NULL); |
| if (err == JVMTI_ERROR_NONE) { |
| NSK_DISPLAY3("for: \tmethod: name=\"%s\" signature=\"%s\"\n\tnative address=0x%p\n", |
| name, sig, code_addr); |
| NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)name); |
| NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)sig); |
| } |
| } |
| |
| static void JNICALL |
| MonitorContendedEnter(jvmtiEnv *jvmti_env, JNIEnv* jni_env, |
| jthread thread, jobject object) { |
| jvmtiThreadInfo info; |
| |
| MonitorContendedEnterEventsCount++; |
| |
| /* get thread information */ |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetThreadInfo, jvmti_env, |
| thread, &info))) { |
| nsk_jvmti_setFailStatus(); |
| return; |
| } |
| NSK_DISPLAY2("MonitorContendedEnter event: thread=\"%s\", object=0x%p\n", |
| info.name, object); |
| } |
| |
| static void JNICALL |
| MonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv* jni_env, |
| jthread thread, jobject object) { |
| jvmtiThreadInfo info; |
| |
| MonitorContendedEnteredEventsCount++; |
| |
| /* get thread information */ |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetThreadInfo, jvmti_env, |
| thread, &info))) { |
| nsk_jvmti_setFailStatus(); |
| return; |
| } |
| NSK_DISPLAY2("MonitorContendedEntered event: thread=\"%s\", object=0x%p\n", |
| info.name, object); |
| } |
| |
| static void JNICALL |
| MonitorWait(jvmtiEnv *jvmti_env, JNIEnv* jni_env, |
| jthread thread, jobject object, jlong timeout) { |
| jvmtiThreadInfo info; |
| |
| MonitorWaitEventsCount++; |
| |
| /* get thread information */ |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetThreadInfo, jvmti_env, |
| thread, &info))) { |
| nsk_jvmti_setFailStatus(); |
| return; |
| } |
| NSK_DISPLAY2("MonitorWait event: thread=\"%s\", object=0x%p\n", |
| info.name, object); |
| } |
| |
| static void JNICALL |
| MonitorWaited(jvmtiEnv *jvmti_env, JNIEnv* jni_env, |
| jthread thread, jobject object, jboolean timed_out) { |
| jvmtiThreadInfo info; |
| |
| MonitorWaitedEventsCount++; |
| |
| /* get thread information */ |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetThreadInfo, jvmti_env, |
| thread, &info))) { |
| nsk_jvmti_setFailStatus(); |
| return; |
| } |
| NSK_DISPLAY2("MonitorWaited event: thread=\"%s\", object=0x%p\n", |
| info.name, object); |
| } |
| |
| static void JNICALL |
| VMObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, |
| jthread thread, jobject object, |
| jclass object_klass, jlong size) { |
| char *signature; |
| |
| VMObjectAllocEventsCount++; |
| |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, jvmti_env, |
| object_klass, &signature, NULL))) { |
| nsk_jvmti_setFailStatus(); |
| return; |
| } |
| NSK_DISPLAY2("VMObjectAlloc: \"%s\", size=%d\n", signature, size); |
| if (signature != NULL) |
| NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)signature); |
| } |
| |
| static void JNICALL |
| NativeMethodBind(jvmtiEnv* jvmti_env, JNIEnv *jni_env, |
| jthread thread, jmethodID method, void* func, void** func_ptr) { |
| jvmtiPhase phase; |
| char *name = NULL; |
| char *signature = NULL; |
| |
| NativeMethodBindEventsCount++; |
| |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti_env, &phase))) { |
| nsk_jvmti_setFailStatus(); |
| return; |
| } |
| |
| if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE) |
| return; |
| |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB5(GetMethodName, |
| jvmti_env, method, &name, &signature, NULL))) { |
| nsk_jvmti_setFailStatus(); |
| return; |
| } |
| |
| NSK_DISPLAY2("NativeMethodBind event: %s%s\n", name, signature); |
| |
| if (name != NULL) |
| NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)name); |
| if (signature != NULL) |
| NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)signature); |
| } |
| |
| static void JNICALL |
| GarbageCollectionStart(jvmtiEnv *jvmti_env) { |
| GarbageCollectionStartEventsCount++; |
| NSK_DISPLAY0("GarbageCollectionStart\n"); |
| } |
| |
| static void JNICALL |
| GarbageCollectionFinish(jvmtiEnv *jvmti_env) { |
| GarbageCollectionFinishEventsCount++; |
| NSK_DISPLAY0("GarbageCollectionFinish\n"); |
| } |
| |
| static void JNICALL |
| ObjectFree(jvmtiEnv *jvmti_env, jlong tag) { |
| char buffer[32]; |
| |
| ObjectFreeEventsCount++; |
| NSK_DISPLAY1("ObjectFree event: tag=%s\n", jlong_to_string(tag, buffer)); |
| } |
| |
| /* ========================================================================== */ |
| |
| static int prepare(jvmtiEnv* jvmti, JNIEnv* jni) { |
| const char* THREAD_NAME = "Debuggee Thread"; |
| jvmtiThreadInfo info; |
| jthread *threads = NULL; |
| jint threads_count = 0; |
| int i; |
| |
| NSK_DISPLAY0("Prepare: find tested thread\n"); |
| |
| /* get all live threads */ |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB3(GetAllThreads, jvmti, &threads_count, &threads))) |
| return NSK_FALSE; |
| |
| if (!NSK_VERIFY(threads_count > 0 && threads != NULL)) |
| return NSK_FALSE; |
| |
| /* find tested thread */ |
| for (i = 0; i < threads_count; i++) { |
| if (!NSK_VERIFY(threads[i] != NULL)) |
| return NSK_FALSE; |
| |
| /* get thread information */ |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB3(GetThreadInfo, jvmti, threads[i], &info))) |
| return NSK_FALSE; |
| |
| NSK_DISPLAY3(" thread #%d (%s): %p\n", i, info.name, threads[i]); |
| |
| /* find by name */ |
| if (info.name != NULL && (strcmp(info.name, THREAD_NAME) == 0)) { |
| thread = threads[i]; |
| } |
| } |
| |
| if (!NSK_JNI_VERIFY(jni, (thread = |
| NSK_CPP_STUB2(NewGlobalRef, jni, thread)) != NULL)) |
| return NSK_FALSE; |
| |
| /* deallocate threads list */ |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)threads))) |
| return NSK_FALSE; |
| |
| /* get tested thread class */ |
| if (!NSK_JNI_VERIFY(jni, (klass = |
| NSK_CPP_STUB2(GetObjectClass, jni, thread)) != NULL)) |
| return NSK_FALSE; |
| |
| return NSK_TRUE; |
| } |
| |
| /* ========================================================================== */ |
| |
| /* Check GetCapabilities function |
| */ |
| static int checkGetCapabilities(jvmtiEnv* jvmti) { |
| jvmtiCapabilities caps; |
| |
| memset(&caps, 0, sizeof(caps)); |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetCapabilities, jvmti, &caps))) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_tag_objects)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_get_owned_monitor_info)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_get_current_contended_monitor)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_get_monitor_info)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_maintain_original_method_order)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_get_current_thread_cpu_time)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_get_thread_cpu_time)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_generate_all_class_hook_events)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_generate_compiled_method_load_events)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_generate_monitor_events)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_generate_vm_object_alloc_events)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_generate_native_method_bind_events)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_generate_garbage_collection_events)) |
| return NSK_FALSE; |
| if (!NSK_VERIFY(caps.can_generate_object_free_events)) |
| return NSK_FALSE; |
| |
| return NSK_TRUE; |
| } |
| |
| /* ========================================================================== */ |
| |
| /* Check "can_get_owned_monitor_info" function |
| */ |
| static int checkGetOwnedMonitorInfo(jvmtiEnv* jvmti) { |
| jint count; |
| jobject *monitors = NULL; |
| |
| NSK_DISPLAY0("Checking positive: GetOwnedMonitorInfo\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB4(GetOwnedMonitorInfo, jvmti, thread, &count, &monitors))) |
| return NSK_FALSE; |
| |
| return NSK_TRUE; |
| } |
| |
| /* Check "can_get_current_contended_monitor" function |
| */ |
| static int checkGetCurrentContendedMonitor(jvmtiEnv* jvmti) { |
| jobject monitor = NULL; |
| |
| NSK_DISPLAY0("Checking positive: GetCurrentContendedMonitor\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB3(GetCurrentContendedMonitor, jvmti, thread, &monitor))) |
| return NSK_FALSE; |
| |
| return NSK_TRUE; |
| } |
| |
| /* Check "can_tag_objects" functions |
| */ |
| |
| static jvmtiIterationControl JNICALL |
| HeapObject(jlong class_tag, jlong size, jlong *tag_ptr, void *user_data) { |
| return JVMTI_ITERATION_CONTINUE; |
| } |
| |
| static jvmtiIterationControl JNICALL |
| HeapRoot(jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, |
| jlong *tag_ptr, void *user_data) { |
| return JVMTI_ITERATION_CONTINUE; |
| } |
| |
| static jvmtiIterationControl JNICALL |
| StackReference(jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, |
| jlong *tag_ptr, jlong thread_tag, jint depth, jmethodID method, |
| jint slot, void *user_data) { |
| return JVMTI_ITERATION_CONTINUE; |
| } |
| |
| static jvmtiIterationControl JNICALL |
| ObjectReference(jvmtiObjectReferenceKind reference_kind, jlong class_tag, |
| jlong size, jlong *tag_ptr, jlong referrer_tag, |
| jint referrer_index, void *user_data) { |
| return JVMTI_ITERATION_CONTINUE; |
| } |
| |
| static jvmtiIterationControl JNICALL |
| ThreadObjectReference(jvmtiObjectReferenceKind reference_kind, jlong class_tag, |
| jlong size, jlong *tag_ptr, jlong referrer_tag, |
| jint referrer_index, void *user_data) { |
| static jlong ThreadObjectReferenceTagCount; |
| *tag_ptr = ++ThreadObjectReferenceTagCount; |
| return JVMTI_ITERATION_CONTINUE; |
| } |
| |
| static int checkHeapFunctions(jvmtiEnv* jvmti) { |
| const jlong TAG_VALUE = (123456789L); |
| jlong tag; |
| jint count; |
| jobject *res_objects = NULL; |
| jlong *res_tags = NULL; |
| jint dummy_user_data = 0; |
| |
| NSK_DISPLAY0("Checking positive: SetTag\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB3(SetTag, jvmti, thread, TAG_VALUE))) |
| return NSK_FALSE; |
| |
| NSK_DISPLAY0("Checking positive: GetTag\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB3(GetTag, jvmti, thread, &tag))) |
| return NSK_FALSE; |
| |
| NSK_DISPLAY0("Checking positive: GetObjectsWithTags\n"); |
| tag = TAG_VALUE; |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB6(GetObjectsWithTags, jvmti, 1, &tag, |
| &count, &res_objects, &res_tags))) |
| return NSK_FALSE; |
| |
| NSK_DISPLAY0("Checking positive: IterateOverHeap\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB4(IterateOverHeap, jvmti, JVMTI_HEAP_OBJECT_TAGGED, |
| HeapObject, &dummy_user_data))) |
| return NSK_FALSE; |
| |
| NSK_DISPLAY0("Checking positive: IterateOverInstancesOfClass\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB5(IterateOverInstancesOfClass, jvmti, klass, |
| JVMTI_HEAP_OBJECT_UNTAGGED, HeapObject, &dummy_user_data))) |
| return NSK_FALSE; |
| |
| NSK_DISPLAY0("Checking positive: IterateOverObjectsReachableFromObject\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB4(IterateOverObjectsReachableFromObject, jvmti, thread, |
| ThreadObjectReference, &dummy_user_data))) |
| return NSK_FALSE; |
| |
| NSK_DISPLAY0("Checking positive: IterateOverReachableObjects\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB5(IterateOverReachableObjects, jvmti, |
| HeapRoot, StackReference, ObjectReference, &dummy_user_data))) |
| return NSK_FALSE; |
| |
| return NSK_TRUE; |
| } |
| |
| /* Check "can_get_monitor_info" function |
| */ |
| static int checkGetObjectMonitorUsage(jvmtiEnv* jvmti) { |
| jvmtiMonitorUsage monitor_info; |
| |
| NSK_DISPLAY0("Checking positive: GetObjectMonitorUsage\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB3(GetObjectMonitorUsage, jvmti, thread, &monitor_info))) |
| return NSK_FALSE; |
| |
| return NSK_TRUE; |
| } |
| |
| /* Check "can_get_current_thread_cpu_time" function |
| */ |
| static int checkGetCurrentThreadCpuTime(jvmtiEnv* jvmti) { |
| jvmtiTimerInfo info; |
| jlong nanos; |
| |
| NSK_DISPLAY0("Checking positive: GetCurrentThreadCpuTimerInfo\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB2(GetCurrentThreadCpuTimerInfo, jvmti, &info))) |
| return NSK_FALSE; |
| |
| NSK_DISPLAY0("Checking positive: GetCurrentThreadCpuTime\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB2(GetCurrentThreadCpuTime, jvmti, &nanos))) |
| return NSK_FALSE; |
| |
| return NSK_TRUE; |
| } |
| |
| /* Check "can_get_thread_cpu_time" function |
| */ |
| static int checkGetThreadCpuTime(jvmtiEnv* jvmti) { |
| jvmtiTimerInfo info; |
| jlong nanos; |
| |
| NSK_DISPLAY0("Checking positive: GetThreadCpuTimerInfo\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB2(GetThreadCpuTimerInfo, jvmti, &info))) |
| return NSK_FALSE; |
| |
| NSK_DISPLAY0("Checking positive: checkGetThreadCpuTime\n"); |
| if (!NSK_JVMTI_VERIFY( |
| NSK_CPP_STUB3(GetThreadCpuTime, jvmti, thread, &nanos))) |
| return NSK_FALSE; |
| |
| return NSK_TRUE; |
| } |
| |
| /* ========================================================================== */ |
| |
| /* Check generated events |
| */ |
| static int checkGeneratedEvents() { |
| int result = NSK_TRUE; |
| |
| NSK_DISPLAY1("ClassFileLoadHook events received: %d\n", |
| ClassFileLoadHookEventsCount); |
| if (!NSK_VERIFY(ClassFileLoadHookEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| NSK_DISPLAY1("CompiledMethodLoad events received: %d\n", |
| CompiledMethodLoadEventsCount); |
| if (CompiledMethodLoadEventsCount == 0) { |
| NSK_DISPLAY0("# WARNING: no CompiledMethodLoad events\n"); |
| NSK_DISPLAY0("# (VM might not compile any methods at all)\n"); |
| } |
| |
| NSK_DISPLAY1("CompiledMethodUnload events received: %d\n", |
| CompiledMethodUnloadEventsCount); |
| if (CompiledMethodUnloadEventsCount == 0) { |
| NSK_DISPLAY0("# WARNING: no CompiledMethodUnload events\n"); |
| NSK_DISPLAY0("# (VM might not compile any methods at all)\n"); |
| } |
| |
| NSK_DISPLAY1("MonitorContendedEnter events received: %d\n", |
| MonitorContendedEnterEventsCount); |
| if (!NSK_VERIFY(MonitorContendedEnterEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| NSK_DISPLAY1("MonitorContendedEntered events received: %d\n", |
| MonitorContendedEnteredEventsCount); |
| if (!NSK_VERIFY(MonitorContendedEnteredEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| NSK_DISPLAY1("MonitorWait events received: %d\n", |
| MonitorWaitEventsCount); |
| if (!NSK_VERIFY(MonitorWaitEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| NSK_DISPLAY1("MonitorWaited events received: %d\n", |
| MonitorWaitedEventsCount); |
| if (!NSK_VERIFY(MonitorWaitedEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| NSK_DISPLAY1("VMObjectAlloc events received: %d\n", |
| VMObjectAllocEventsCount); |
| if (!NSK_VERIFY(VMObjectAllocEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| NSK_DISPLAY1("NativeMethodBind events received: %d\n", |
| NativeMethodBindEventsCount); |
| if (!NSK_VERIFY(NativeMethodBindEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| NSK_DISPLAY1("GarbageCollectionStart events received: %d\n", |
| GarbageCollectionStartEventsCount); |
| if (!NSK_VERIFY(GarbageCollectionStartEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| NSK_DISPLAY1("GarbageCollectionFinish events received: %d\n", |
| GarbageCollectionFinishEventsCount); |
| if (!NSK_VERIFY(GarbageCollectionFinishEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| NSK_DISPLAY1("ObjectFree events received: %d\n", |
| ObjectFreeEventsCount); |
| if (!NSK_VERIFY(ObjectFreeEventsCount != 0)) |
| result = NSK_FALSE; |
| |
| return result; |
| } |
| |
| /* ========================================================================== */ |
| |
| /* agent algorithm */ |
| static void JNICALL |
| agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { |
| |
| /* wait for initial sync */ |
| if (!nsk_jvmti_waitForSync(timeout)) |
| return; |
| |
| if (!prepare(jvmti, jni)) { |
| nsk_jvmti_setFailStatus(); |
| return; |
| } |
| |
| NSK_DISPLAY0("Testcase #1: check if GetCapabilities returns the capabilities\n"); |
| if (!checkGetCapabilities(jvmti)) { |
| nsk_jvmti_setFailStatus(); |
| } |
| |
| NSK_DISPLAY0("Testcase #2: check if all correspondent functions work\n"); |
| if (!checkGetOwnedMonitorInfo(jvmti)) |
| nsk_jvmti_setFailStatus(); |
| if (!checkGetCurrentContendedMonitor(jvmti)) |
| nsk_jvmti_setFailStatus(); |
| if (!checkHeapFunctions(jvmti)) |
| nsk_jvmti_setFailStatus(); |
| if (!checkGetObjectMonitorUsage(jvmti)) |
| nsk_jvmti_setFailStatus(); |
| if (!checkGetCurrentThreadCpuTime(jvmti)) |
| nsk_jvmti_setFailStatus(); |
| if (!checkGetThreadCpuTime(jvmti)) |
| nsk_jvmti_setFailStatus(); |
| |
| NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, thread)); |
| |
| /* resume debugee and wait for sync */ |
| if (!nsk_jvmti_resumeSync()) |
| return; |
| if (!nsk_jvmti_waitForSync(timeout)) |
| return; |
| |
| NSK_DISPLAY0("Testcase #3: check if the events are generated\n"); |
| if (!checkGeneratedEvents()) { |
| nsk_jvmti_setFailStatus(); |
| } |
| |
| /* resume debugee after last sync */ |
| if (!nsk_jvmti_resumeSync()) |
| return; |
| } |
| |
| /* ========================================================================== */ |
| |
| /* agent library initialization */ |
| #ifdef STATIC_BUILD |
| JNIEXPORT jint JNICALL Agent_OnLoad_cm02t001(JavaVM *jvm, char *options, void *reserved) { |
| return Agent_Initialize(jvm, options, reserved); |
| } |
| JNIEXPORT jint JNICALL Agent_OnAttach_cm02t001(JavaVM *jvm, char *options, void *reserved) { |
| return Agent_Initialize(jvm, options, reserved); |
| } |
| JNIEXPORT jint JNI_OnLoad_cm02t001(JavaVM *jvm, char *options, void *reserved) { |
| return JNI_VERSION_1_8; |
| } |
| #endif |
| jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { |
| jvmtiEnv* jvmti = NULL; |
| jvmtiCapabilities caps; |
| jvmtiEventCallbacks callbacks; |
| |
| /* init framework and parse options */ |
| if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) |
| return JNI_ERR; |
| |
| timeout = nsk_jvmti_getWaitTime() * 60000; |
| NSK_DISPLAY1("Timeout: %d msc\n", (int)timeout); |
| |
| /* create JVMTI environment */ |
| if (!NSK_VERIFY((jvmti = |
| nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) |
| return JNI_ERR; |
| |
| /* add capabilities */ |
| memset(&caps, 0, sizeof(caps)); |
| caps.can_tag_objects = 1; |
| caps.can_get_owned_monitor_info = 1; |
| caps.can_get_current_contended_monitor = 1; |
| caps.can_get_monitor_info = 1; |
| caps.can_maintain_original_method_order = 1; |
| caps.can_get_current_thread_cpu_time = 1; |
| caps.can_get_thread_cpu_time = 1; |
| caps.can_generate_all_class_hook_events = 1; |
| caps.can_generate_compiled_method_load_events = 1; |
| caps.can_generate_monitor_events = 1; |
| caps.can_generate_vm_object_alloc_events = 1; |
| caps.can_generate_native_method_bind_events = 1; |
| caps.can_generate_garbage_collection_events = 1; |
| caps.can_generate_object_free_events = 1; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) |
| return JNI_ERR; |
| |
| /* set event callbacks */ |
| memset(&callbacks, 0, sizeof(callbacks)); |
| callbacks.ClassFileLoadHook = &ClassFileLoadHook; |
| callbacks.CompiledMethodLoad = &CompiledMethodLoad; |
| callbacks.CompiledMethodUnload = &CompiledMethodUnload; |
| callbacks.MonitorContendedEnter = &MonitorContendedEnter; |
| callbacks.MonitorContendedEntered = &MonitorContendedEntered; |
| callbacks.MonitorWait = &MonitorWait; |
| callbacks.MonitorWaited = &MonitorWaited; |
| callbacks.VMObjectAlloc = &VMObjectAlloc; |
| callbacks.NativeMethodBind = &NativeMethodBind; |
| callbacks.GarbageCollectionStart = &GarbageCollectionStart; |
| callbacks.GarbageCollectionFinish = &GarbageCollectionFinish; |
| callbacks.ObjectFree = &ObjectFree; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetEventCallbacks, |
| jvmti, &callbacks, sizeof(callbacks)))) |
| return JNI_ERR; |
| |
| /* enable events */ |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_UNLOAD, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_CONTENDED_ENTER, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAIT, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAITED, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_NATIVE_METHOD_BIND, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_START, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL))) |
| return JNI_ERR; |
| if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode, |
| jvmti, JVMTI_ENABLE, JVMTI_EVENT_OBJECT_FREE, NULL))) |
| return JNI_ERR; |
| |
| /* register agent proc and arg */ |
| if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) |
| return JNI_ERR; |
| |
| return JNI_OK; |
| } |
| |
| /* ========================================================================== */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |