blob: b61d254f41b9be3996c081fabf009ccfef9b89d4 [file] [log] [blame]
/*
* Copyright (c) 2003, 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 <stdlib.h>
#include <string.h>
#include "native_thread.h"
#include "jni_tools.h"
#include "jvmti_tools.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================= */
/* Be careful: do not build shared library which will be linked with different
* agent libs while global variables are used
* Now the same source is used to build different agent libs, so these
* variables are not shared between agents */
static jthread agentThread = NULL;
static jvmtiStartFunction agentThreadProc = NULL;
static void* agentThreadArg = NULL;
typedef enum {NEW, RUNNABLE, WAITING, SUSPENDED, TERMINATED} thread_state_t;
typedef struct agent_data_t {
volatile thread_state_t thread_state;
int last_debuggee_status;
jrawMonitorID monitor;
} agent_data_t;
static agent_data_t agent_data;
static jvmtiEnv* jvmti_env = NULL;
static JavaVM* jvm = NULL;
static JNIEnv* jni_env = NULL;
static volatile int currentAgentStatus = NSK_STATUS_PASSED;
/* ============================================================================= */
void nsk_jvmti_setFailStatus() {
currentAgentStatus = NSK_STATUS_FAILED;
}
int nsk_jvmti_isFailStatus() {
return (nsk_jvmti_getStatus() != NSK_STATUS_PASSED);
}
jint nsk_jvmti_getStatus() {
return currentAgentStatus;
}
/* ============================================================================= */
static jvmtiError init_agent_data(jvmtiEnv *jvmti_env, agent_data_t *data) {
data->thread_state = NEW;
data->last_debuggee_status = NSK_STATUS_PASSED;
return NSK_CPP_STUB3(CreateRawMonitor, jvmti_env, "agent_data_monitor", &data->monitor);
}
/** Reset agent data to prepare for another run. */
void nsk_jvmti_resetAgentData() {
rawMonitorEnter(jvmti_env, agent_data.monitor);
/* wait for agentThreadWrapper() to finish */
while (agent_data.thread_state != TERMINATED) {
rawMonitorWait(jvmti_env, agent_data.monitor, 10);
}
agent_data.thread_state = NEW;
agent_data.last_debuggee_status = NSK_STATUS_PASSED;
rawMonitorExit(jvmti_env, agent_data.monitor);
}
static jvmtiError free_agent_data(jvmtiEnv *jvmti_env, agent_data_t *data) {
return NSK_CPP_STUB2(DestroyRawMonitor, jvmti_env, data->monitor);
}
/** Create JVMTI environment. */
jvmtiEnv* nsk_jvmti_createJVMTIEnv(JavaVM* javaVM, void* reserved) {
jvm = javaVM;
if (!NSK_VERIFY(
NSK_CPP_STUB3(GetEnv, javaVM, (void **)&jvmti_env, JVMTI_VERSION_1_1) == JNI_OK)) {
nsk_jvmti_setFailStatus();
return NULL;
}
if (!NSK_JVMTI_VERIFY(init_agent_data(jvmti_env, &agent_data))) {
nsk_jvmti_setFailStatus();
return NULL;
}
return jvmti_env;
}
/** Dispose JVMTI environment */
static int nsk_jvmti_disposeJVMTIEnv(jvmtiEnv* jvmti_env) {
if (jvmti_env != NULL) {
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB1(DisposeEnvironment, jvmti_env))) {
nsk_jvmti_setFailStatus();
return NSK_FALSE;
}
if (!NSK_JVMTI_VERIFY(free_agent_data(jvmti_env, &agent_data))) {
nsk_jvmti_setFailStatus();
return NSK_FALSE;
}
}
return NSK_TRUE;
}
/** Get JNI environment for agent thread. */
JNIEnv* nsk_jvmti_getAgentJNIEnv() {
return jni_env;
}
/** Get JVMTI environment for agent */
jvmtiEnv* nsk_jvmti_getAgentJVMTIEnv() {
return jvmti_env;
}
/* ============================================================================= */
static void set_agent_thread_state(thread_state_t value) {
rawMonitorEnter(jvmti_env, agent_data.monitor);
agent_data.thread_state = value;
rawMonitorNotify(jvmti_env, agent_data.monitor);
rawMonitorExit(jvmti_env, agent_data.monitor);
}
/** Wrapper for user agent thread. */
static void JNICALL
agentThreadWrapper(jvmtiEnv* jvmti_env, JNIEnv* agentJNI, void* arg) {
jni_env = agentJNI;
/* run user agent proc */
{
set_agent_thread_state(RUNNABLE);
NSK_TRACE((*agentThreadProc)(jvmti_env, agentJNI, agentThreadArg));
set_agent_thread_state(TERMINATED);
}
/* finalize agent thread */
{
/* gelete global ref for agent thread */
NSK_CPP_STUB2(DeleteGlobalRef, agentJNI, agentThread);
agentThread = NULL;
}
}
/** Start wrapper for user agent thread. */
static jthread startAgentThreadWrapper(JNIEnv *jni_env, jvmtiEnv* jvmti_env) {
const jint THREAD_PRIORITY = JVMTI_THREAD_MAX_PRIORITY;
const char* THREAD_NAME = "JVMTI agent thread";
const char* THREAD_CLASS_NAME = "java/lang/Thread";
const char* THREAD_CTOR_NAME = "<init>";
const char* THREAD_CTOR_SIGNATURE = "(Ljava/lang/String;)V";
jobject threadName = NULL;
jclass threadClass = NULL;
jmethodID threadCtor = NULL;
jobject threadObject = NULL;
jobject threadGlobalRef = NULL;
if (!NSK_JNI_VERIFY(jni_env, (threadClass =
NSK_CPP_STUB2(FindClass, jni_env, THREAD_CLASS_NAME)) != NULL)) {
return NULL;
}
if (!NSK_JNI_VERIFY(jni_env, (threadCtor =
NSK_CPP_STUB4(GetMethodID, jni_env, threadClass, THREAD_CTOR_NAME, THREAD_CTOR_SIGNATURE)) != NULL))
return NULL;
if (!NSK_JNI_VERIFY(jni_env, (threadName =
NSK_CPP_STUB2(NewStringUTF, jni_env, THREAD_NAME)) != NULL))
return NULL;
if (!NSK_JNI_VERIFY(jni_env, (threadObject =
NSK_CPP_STUB4(NewObject, jni_env, threadClass, threadCtor, threadName)) != NULL))
return NULL;
if (!NSK_JNI_VERIFY(jni_env, (threadGlobalRef =
NSK_CPP_STUB2(NewGlobalRef, jni_env, threadObject)) != NULL)) {
NSK_CPP_STUB2(DeleteLocalRef, jni_env, threadObject);
return NULL;
}
agentThread = (jthread)threadGlobalRef;
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB5(RunAgentThread, jvmti_env, agentThread,
&agentThreadWrapper, agentThreadArg, THREAD_PRIORITY))) {
NSK_CPP_STUB2(DeleteGlobalRef, jni_env, threadGlobalRef);
NSK_CPP_STUB2(DeleteLocalRef, jni_env, threadObject);
return NULL;
}
return agentThread;
}
/** Register user agent thread with arg. */
int nsk_jvmti_setAgentProc(jvmtiStartFunction proc, void* arg) {
agentThreadProc = proc;
agentThreadArg = arg;
return NSK_TRUE;
}
/** Get agent thread ref. */
jthread nsk_jvmti_getAgentThread() {
return agentThread;
}
/** Run registered user agent thread via wrapper. */
static jthread nsk_jvmti_runAgentThread(JNIEnv *jni_env, jvmtiEnv* jvmti_env) {
/* start agent thread wrapper */
jthread thread = startAgentThreadWrapper(jni_env, jvmti_env);
if (thread == NULL) {
nsk_jvmti_setFailStatus();
return NULL;
}
return thread;
}
/* ============================================================================= */
/** Sleep current thread. */
void nsk_jvmti_sleep(jlong timeout) {
int seconds = (int)((timeout + 999) / 1000);
THREAD_sleep(seconds);
}
/** Sync point called from Java code. */
static jint syncDebuggeeStatus(JNIEnv* jni_env, jvmtiEnv* jvmti_env, jint debuggeeStatus) {
jint result = NSK_STATUS_FAILED;
rawMonitorEnter(jvmti_env, agent_data.monitor);
/* save last debugee status */
agent_data.last_debuggee_status = debuggeeStatus;
/* we don't enter if-stmt in second call */
if (agent_data.thread_state == NEW) {
if (nsk_jvmti_runAgentThread(jni_env, jvmti_env) == NULL)
goto monitor_exit_and_return;
/* SP2.2-w - wait for agent thread */
while (agent_data.thread_state == NEW) {
rawMonitorWait(jvmti_env, agent_data.monitor, 0);
}
}
/* wait for sync permit */
/* we don't enter loop in first call */
while (agent_data.thread_state != WAITING && agent_data.thread_state != TERMINATED) {
/* SP4.2-w - second wait for agent thread */
rawMonitorWait(jvmti_env, agent_data.monitor, 0);
}
if (agent_data.thread_state != TERMINATED) {
agent_data.thread_state = SUSPENDED;
/* SP3.2-n - notify to start test */
/* SP6.2-n - notify to end test */
rawMonitorNotify(jvmti_env, agent_data.monitor);
}
else {
NSK_COMPLAIN0("Debuggee status sync aborted because agent thread has finished\n");
goto monitor_exit_and_return;
}
/* update status from debuggee */
if (debuggeeStatus != NSK_STATUS_PASSED) {
nsk_jvmti_setFailStatus();
}
while (agent_data.thread_state == SUSPENDED) {
/* SP5.2-w - wait while testing */
/* SP7.2 - wait for agent end */
rawMonitorWait(jvmti_env, agent_data.monitor, 0);
}
agent_data.last_debuggee_status = nsk_jvmti_getStatus();
result = agent_data.last_debuggee_status;
monitor_exit_and_return:
rawMonitorExit(jvmti_env, agent_data.monitor);
return result;
}
/** Wait for sync point with Java code. */
int nsk_jvmti_waitForSync(jlong timeout) {
static const int inc_timeout = 1000;
jlong t = 0;
int result = NSK_TRUE;
rawMonitorEnter(jvmti_env, agent_data.monitor);
agent_data.thread_state = WAITING;
/* SP2.2-n - notify agent is waiting and wait */
/* SP4.1-n - notify agent is waiting and wait */
rawMonitorNotify(jvmti_env, agent_data.monitor);
while (agent_data.thread_state == WAITING) {
/* SP3.2-w - wait to start test */
/* SP6.2-w - wait to end test */
rawMonitorWait(jvmti_env, agent_data.monitor, inc_timeout);
if (timeout == 0) continue;
t += inc_timeout;
if (t >= timeout) break;
}
if (agent_data.thread_state == WAITING) {
NSK_COMPLAIN1("No status sync occured for timeout: %"LL"d ms\n", timeout);
nsk_jvmti_setFailStatus();
result = NSK_FALSE;
}
rawMonitorExit(jvmti_env, agent_data.monitor);
return result;
}
/** Resume java code suspended on sync point. */
int nsk_jvmti_resumeSync() {
int result;
rawMonitorEnter(jvmti_env, agent_data.monitor);
if (agent_data.thread_state == SUSPENDED) {
result = NSK_TRUE;
agent_data.thread_state = RUNNABLE;
/* SP5.2-n - notify suspend done */
/* SP7.2-n - notify agent end */
rawMonitorNotify(jvmti_env, agent_data.monitor);
}
else {
NSK_COMPLAIN0("Debuggee was not suspended on status sync\n");
nsk_jvmti_setFailStatus();
result = NSK_FALSE;
}
rawMonitorExit(jvmti_env, agent_data.monitor);
return NSK_TRUE;
}
/** Native function for Java code to provide sync point. */
JNIEXPORT jint JNICALL
Java_nsk_share_jvmti_DebugeeClass_checkStatus(JNIEnv* jni_env, jclass cls, jint debuggeeStatus) {
jint status;
NSK_TRACE(status = syncDebuggeeStatus(jni_env, jvmti_env, debuggeeStatus));
return status;
}
/** Native function for Java code to reset agent data. */
JNIEXPORT void JNICALL
Java_nsk_share_jvmti_DebugeeClass_resetAgentData(JNIEnv* jni_env, jclass cls) {
NSK_TRACE(nsk_jvmti_resetAgentData());
}
/* ============================================================================= */
/** Find loaded class by signature. */
jclass nsk_jvmti_classBySignature(const char signature[]) {
jclass* classes = NULL;
jint count = 0;
jclass foundClass = NULL;
int i;
if (!NSK_VERIFY(signature != NULL)) {
nsk_jvmti_setFailStatus();
return NULL;
}
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB3(GetLoadedClasses, jvmti_env, &count, &classes))) {
nsk_jvmti_setFailStatus();
return NULL;
}
for (i = 0; i < count; i++) {
char* sig = NULL;
char* generic = NULL;
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB4(GetClassSignature, jvmti_env, classes[i], &sig, &generic))) {
nsk_jvmti_setFailStatus();
break;
}
if (sig != NULL && strcmp(signature, sig) == 0) {
foundClass = classes[i];
}
if (!(NSK_JVMTI_VERIFY(
NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)sig))
&& NSK_JVMTI_VERIFY(
NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)generic)))) {
nsk_jvmti_setFailStatus();
break;
}
if (foundClass != NULL)
break;
}
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)classes))) {
nsk_jvmti_setFailStatus();
return NULL;
}
if (!NSK_JNI_VERIFY(jni_env, (foundClass = (jclass)
NSK_CPP_STUB2(NewGlobalRef, jni_env, foundClass)) != NULL)) {
nsk_jvmti_setFailStatus();
return NULL;
}
return foundClass;
}
/** Find alive thread by name. */
jthread nsk_jvmti_threadByName(const char name[]) {
jthread* threads = NULL;
jint count = 0;
jthread foundThread = NULL;
int i;
if (!NSK_VERIFY(name != NULL)) {
nsk_jvmti_setFailStatus();
return NULL;
}
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB3(GetAllThreads, jvmti_env, &count, &threads))) {
nsk_jvmti_setFailStatus();
return NULL;
}
for (i = 0; i < count; i++) {
jvmtiThreadInfo info;
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB3(GetThreadInfo, jvmti_env, threads[i], &info))) {
nsk_jvmti_setFailStatus();
break;
}
if (info.name != NULL && strcmp(name, info.name) == 0) {
foundThread = threads[i];
break;
}
}
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)threads))) {
nsk_jvmti_setFailStatus();
return NULL;
}
if (!NSK_JNI_VERIFY(jni_env, (foundThread = (jthread)
NSK_CPP_STUB2(NewGlobalRef, jni_env, foundThread)) != NULL)) {
nsk_jvmti_setFailStatus();
return NULL;
}
return foundThread;
}
/* ============================================================================= */
/** Add all capabilities for finding line locations. */
int nsk_jvmti_addLocationCapabilities() {
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
caps.can_get_line_numbers = 1;
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB2(AddCapabilities, jvmti_env, &caps)))
return NSK_FALSE;
return NSK_TRUE;
}
/** Add all capabilities for using breakpoints. */
int nsk_jvmti_addBreakpointCapabilities() {
jvmtiCapabilities caps;
if (!nsk_jvmti_addLocationCapabilities())
return NSK_FALSE;
memset(&caps, 0, sizeof(caps));
caps.can_generate_breakpoint_events = 1;
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB2(AddCapabilities, jvmti_env, &caps)))
return NSK_FALSE;
return NSK_TRUE;
}
/** Find line location. */
jlocation nsk_jvmti_getLineLocation(jclass cls, jmethodID method, int line) {
jint count = 0;
jvmtiLineNumberEntry* table = NULL;
jlocation location = NSK_JVMTI_INVALID_JLOCATION;
int i;
if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetLineNumberTable, jvmti_env, method, &count, &table)))
return NSK_JVMTI_INVALID_JLOCATION;
for (i = 0; i < count; i++) {
if (table[i].line_number == line) {
location = table[i].start_location;
break;
}
}
if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)table)))
return NSK_JVMTI_INVALID_JLOCATION;
return location;
}
/** Set breakpoint to a line. */
jlocation nsk_jvmti_setLineBreakpoint(jclass cls, jmethodID method, int line) {
jlocation location = NSK_JVMTI_INVALID_JLOCATION;
if (!NSK_VERIFY((location =
nsk_jvmti_getLineLocation(cls, method, line)) != NSK_JVMTI_INVALID_JLOCATION))
return NSK_JVMTI_INVALID_JLOCATION;
if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetBreakpoint, jvmti_env, method, location)))
return NSK_JVMTI_INVALID_JLOCATION;
return location;
}
/** Remove breakpoint from a line. */
jlocation nsk_jvmti_clearLineBreakpoint(jclass cls, jmethodID method, int line) {
jlocation location = NSK_JVMTI_INVALID_JLOCATION;
if (!NSK_VERIFY((location =
nsk_jvmti_getLineLocation(cls, method, line)) != NSK_JVMTI_INVALID_JLOCATION))
return NSK_JVMTI_INVALID_JLOCATION;
if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(ClearBreakpoint, jvmti_env, method, location)))
return NSK_JVMTI_INVALID_JLOCATION;
return location;
}
/* ============================================================================= */
/** Enable or disable given events. */
int nsk_jvmti_enableEvents(jvmtiEventMode enable, int size, jvmtiEvent list[], jthread thread) {
int i;
for (i = 0; i < size; i++) {
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB4(SetEventNotificationMode, jvmti_env, enable,
list[i], thread))) {
nsk_jvmti_setFailStatus();
return NSK_FALSE;
}
}
return NSK_TRUE;
}
/* ============================================================================= */
typedef jint (JNICALL *checkStatus_type)(JNIEnv* jni_env, jclass cls, jint debuggeeStatus);
static checkStatus_type checkStatus_func = NULL;
/**
* Proxy function to gain sequential access to checkStatus of each agent
*/
JNIEXPORT jint JNICALL
MA_checkStatus(JNIEnv* jni_env, jclass cls, jint debuggeeStatus) {
jint status;
NSK_TRACE(status = syncDebuggeeStatus(jni_env, jvmti_env, debuggeeStatus));
return (*checkStatus_func)(jni_env, cls, status);
}
/**
* nativeMethodBind callback:
* if needed, redirects checkStatus native method call
*/
static void JNICALL nativeMethodBind(jvmtiEnv* jvmti_env, JNIEnv *jni_env,
jthread thread, jmethodID mid,
void* address, void** new_address_ptr) {
const char* BIND_CLASS_NAME = "Lnsk/share/jvmti/DebugeeClass;";
const char* BIND_METHOD_NAME = "checkStatus";
const char* BIND_METHOD_SIGNATURE = "(I)I";
jvmtiPhase phase;
jclass cls;
char *class_sig = NULL;
char *name = NULL;
char *sig = NULL;
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, mid, &name, &sig, NULL))) {
if (strcmp(name, BIND_METHOD_NAME) == 0 &&
strcmp(sig, BIND_METHOD_SIGNATURE) == 0) {
if (NSK_JVMTI_VERIFY(
NSK_CPP_STUB3(GetMethodDeclaringClass, jvmti_env, mid, &cls))
&& NSK_JVMTI_VERIFY(
NSK_CPP_STUB4(GetClassSignature, jvmti_env, cls, &class_sig, NULL))
&& strcmp(class_sig, BIND_CLASS_NAME) == 0
&& address != (void*)Java_nsk_share_jvmti_DebugeeClass_checkStatus) {
checkStatus_func = (checkStatus_type)address;
NSK_TRACE(*new_address_ptr = (void*)MA_checkStatus);
}
}
}
if (name != NULL)
NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)name);
if (sig != NULL)
NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)sig);
if (class_sig != NULL)
NSK_CPP_STUB2(Deallocate, jvmti_env, (unsigned char*)class_sig);
}
/**
* Initialize multiple agent:
* establish processing of nativeMethodBind events
*/
int nsk_jvmti_init_MA(jvmtiEventCallbacks* callbacks) {
if (callbacks == NULL) {
NSK_COMPLAIN0("callbacks should not be NULL\n");
nsk_jvmti_setFailStatus();
return NSK_FALSE;
}
if (callbacks->NativeMethodBind != NULL) {
NSK_COMPLAIN0("callbacks.NativeMethodBind should be NULL\n");
nsk_jvmti_setFailStatus();
return NSK_FALSE;
}
{
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
caps.can_generate_native_method_bind_events = 1;
if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti_env, &caps)))
return NSK_FALSE;
}
callbacks->NativeMethodBind = nativeMethodBind;
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB3(SetEventCallbacks, jvmti_env, callbacks,
sizeof(jvmtiEventCallbacks))))
return NSK_FALSE;
if (!NSK_JVMTI_VERIFY(
NSK_CPP_STUB4(SetEventNotificationMode, jvmti_env, JVMTI_ENABLE,
JVMTI_EVENT_NATIVE_METHOD_BIND, NULL)))
return NSK_FALSE;
return NSK_TRUE;
}
/* ============================================================================= */
int nsk_jvmti_isOptionalEvent(jvmtiEvent event) {
return (event == JVMTI_EVENT_EXCEPTION)
|| (event == JVMTI_EVENT_EXCEPTION_CATCH)
|| (event == JVMTI_EVENT_SINGLE_STEP)
|| (event == JVMTI_EVENT_FRAME_POP)
|| (event == JVMTI_EVENT_BREAKPOINT)
|| (event == JVMTI_EVENT_FIELD_ACCESS)
|| (event == JVMTI_EVENT_FIELD_MODIFICATION)
|| (event == JVMTI_EVENT_METHOD_ENTRY)
|| (event == JVMTI_EVENT_METHOD_EXIT)
|| (event == JVMTI_EVENT_NATIVE_METHOD_BIND)
|| (event == JVMTI_EVENT_COMPILED_METHOD_LOAD)
|| (event == JVMTI_EVENT_COMPILED_METHOD_UNLOAD)
|| (event == JVMTI_EVENT_MONITOR_WAIT)
|| (event == JVMTI_EVENT_MONITOR_WAITED)
|| (event == JVMTI_EVENT_MONITOR_CONTENDED_ENTER)
|| (event == JVMTI_EVENT_MONITOR_CONTENDED_ENTERED)
|| (event == JVMTI_EVENT_GARBAGE_COLLECTION_START)
|| (event == JVMTI_EVENT_GARBAGE_COLLECTION_FINISH)
|| (event == JVMTI_EVENT_OBJECT_FREE)
|| (event == JVMTI_EVENT_VM_OBJECT_ALLOC);
}
/* ============================================================================= */
void nsk_jvmti_showPossessedCapabilities(jvmtiEnv *jvmti_env) {
jvmtiCapabilities caps;
if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetCapabilities, jvmti_env, &caps))) {
return;
}
NSK_DISPLAY0("\n");
NSK_DISPLAY0("Possessed capabilities:\n");
NSK_DISPLAY0("-----------------------\n");
if (caps.can_tag_objects)
NSK_DISPLAY0("\tcan_tag_objects\n");
if (caps.can_generate_field_modification_events)
NSK_DISPLAY0("\tcan_generate_field_modification_events\n");
if (caps.can_generate_field_access_events)
NSK_DISPLAY0("\tcan_generate_field_access_events\n");
if (caps.can_get_bytecodes)
NSK_DISPLAY0("\tcan_get_bytecodes\n");
if (caps.can_get_synthetic_attribute)
NSK_DISPLAY0("\tcan_get_synthetic_attribute\n");
if (caps.can_get_owned_monitor_info)
NSK_DISPLAY0("\tcan_get_owned_monitor_info\n");
if (caps.can_get_current_contended_monitor)
NSK_DISPLAY0("\tcan_get_current_contended_monitor\n");
if (caps.can_get_monitor_info)
NSK_DISPLAY0("\tcan_get_monitor_info\n");
if (caps.can_pop_frame)
NSK_DISPLAY0("\tcan_pop_frame\n");
if (caps.can_redefine_classes)
NSK_DISPLAY0("\tcan_redefine_classes\n");
if (caps.can_signal_thread)
NSK_DISPLAY0("\tcan_signal_thread\n");
if (caps.can_get_source_file_name)
NSK_DISPLAY0("\tcan_get_source_file_name\n");
if (caps.can_get_line_numbers)
NSK_DISPLAY0("\tcan_get_line_numbers\n");
if (caps.can_get_source_debug_extension)
NSK_DISPLAY0("\tcan_get_source_debug_extension\n");
if (caps.can_access_local_variables)
NSK_DISPLAY0("\tcan_access_local_variables\n");
if (caps.can_maintain_original_method_order)
NSK_DISPLAY0("\tcan_maintain_original_method_order\n");
if (caps.can_generate_single_step_events)
NSK_DISPLAY0("\tcan_generate_single_step_events\n");
if (caps.can_generate_exception_events)
NSK_DISPLAY0("\tcan_generate_exception_events\n");
if (caps.can_generate_frame_pop_events)
NSK_DISPLAY0("\tcan_generate_frame_pop_events\n");
if (caps.can_generate_breakpoint_events)
NSK_DISPLAY0("\tcan_generate_breakpoint_events\n");
if (caps.can_suspend)
NSK_DISPLAY0("\tcan_suspend\n");
if (caps.can_get_current_thread_cpu_time)
NSK_DISPLAY0("\tcan_get_current_thread_cpu_time\n");
if (caps.can_get_thread_cpu_time)
NSK_DISPLAY0("\tcan_get_thread_cpu_time\n");
if (caps.can_generate_method_entry_events)
NSK_DISPLAY0("\tcan_generate_method_entry_events\n");
if (caps.can_generate_method_exit_events)
NSK_DISPLAY0("\tcan_generate_method_exit_events\n");
if (caps.can_generate_all_class_hook_events)
NSK_DISPLAY0("\tcan_generate_all_class_hook_events\n");
if (caps.can_generate_compiled_method_load_events)
NSK_DISPLAY0("\tcan_generate_compiled_method_load_events\n");
if (caps.can_generate_monitor_events)
NSK_DISPLAY0("\tcan_generate_monitor_events\n");
if (caps.can_generate_vm_object_alloc_events)
NSK_DISPLAY0("\tcan_generate_vm_object_alloc_events\n");
if (caps.can_generate_native_method_bind_events)
NSK_DISPLAY0("\tcan_generate_native_method_bind_events\n");
if (caps.can_generate_garbage_collection_events)
NSK_DISPLAY0("\tcan_generate_garbage_collection_events\n");
if (caps.can_generate_object_free_events)
NSK_DISPLAY0("\tcan_generate_object_free_events\n");
NSK_DISPLAY0("\n");
}
/* ============================================================================= */
#ifdef __cplusplus
}
#endif