Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/waiters/waiters.cpp
38829 views
/*1* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/383940/* Example of using JVMTI events:41* JVMTI_EVENT_VM_INIT42* JVMTI_EVENT_VM_DEATH43* JVMTI_EVENT_THREAD_START44* JVMTI_EVENT_THREAD_END45* JVMTI_EVENT_MONITOR_CONTENDED_ENTER46* JVMTI_EVENT_MONITOR_WAIT47* JVMTI_EVENT_MONITOR_WAITED48* JVMTI_EVENT_OBJECT_FREE49*/5051#include <stdio.h>52#include <stdlib.h>53#include <string.h>5455#include "jni.h"56#include "jvmti.h"5758#include "agent_util.h"5960#include "Monitor.hpp"61#include "Thread.hpp"62#include "Agent.hpp"6364static jrawMonitorID vm_death_lock;65static jboolean vm_death_active;6667/* Given a jvmtiEnv*, return the C++ Agent class instance */68static Agent *69get_agent(jvmtiEnv *jvmti)70{71jvmtiError err;72Agent *agent;7374agent = NULL;75err = jvmti->GetEnvironmentLocalStorage((void**)&agent);76check_jvmti_error(jvmti, err, "get env local storage");77if ( agent == NULL ) {78/* This should never happen, but we should check */79fatal_error("ERROR: GetEnvironmentLocalStorage() returned NULL");80}81return agent;82}8384/* Enter raw monitor */85static void86menter(jvmtiEnv *jvmti, jrawMonitorID rmon)87{88jvmtiError err;8990err = jvmti->RawMonitorEnter(rmon);91check_jvmti_error(jvmti, err, "raw monitor enter");92}9394/* Exit raw monitor */95static void96mexit(jvmtiEnv *jvmti, jrawMonitorID rmon)97{98jvmtiError err;99100err = jvmti->RawMonitorExit(rmon);101check_jvmti_error(jvmti, err, "raw monitor exit");102}103104105/* All callbacks need to be extern "C" */106extern "C" {107static void JNICALL108vm_init(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)109{110jvmtiError err;111Agent *agent;112113/* Create raw monitor to protect against threads running after death */114err = jvmti->CreateRawMonitor("Waiters vm_death lock", &vm_death_lock);115check_jvmti_error(jvmti, err, "create raw monitor");116vm_death_active = JNI_FALSE;117118/* Create an Agent instance, set JVMTI Local Storage */119agent = new Agent(jvmti, env, thread);120err = jvmti->SetEnvironmentLocalStorage((const void*)agent);121check_jvmti_error(jvmti, err, "set env local storage");122123/* Enable all other events we want */124err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,125JVMTI_EVENT_VM_DEATH, NULL);126check_jvmti_error(jvmti, err, "set event notify");127err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,128JVMTI_EVENT_THREAD_START, NULL);129check_jvmti_error(jvmti, err, "set event notify");130err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,131JVMTI_EVENT_THREAD_END, NULL);132check_jvmti_error(jvmti, err, "set event notify");133err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,134JVMTI_EVENT_MONITOR_CONTENDED_ENTER, NULL);135check_jvmti_error(jvmti, err, "set event notify");136err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,137JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL);138check_jvmti_error(jvmti, err, "set event notify");139err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,140JVMTI_EVENT_MONITOR_WAIT, NULL);141check_jvmti_error(jvmti, err, "set event notify");142err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,143JVMTI_EVENT_MONITOR_WAITED, NULL);144check_jvmti_error(jvmti, err, "set event notify");145err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,146JVMTI_EVENT_OBJECT_FREE, NULL);147check_jvmti_error(jvmti, err, "set event notify");148}149static void JNICALL150vm_death(jvmtiEnv *jvmti, JNIEnv *env)151{152jvmtiError err;153Agent *agent;154155/* Block all callbacks */156menter(jvmti, vm_death_lock); {157/* Set flag for other callbacks */158vm_death_active = JNI_TRUE;159160/* Inform Agent instance of VM_DEATH */161agent = get_agent(jvmti);162agent->vm_death(jvmti, env);163164/* Reclaim space of Agent */165err = jvmti->SetEnvironmentLocalStorage((const void*)NULL);166check_jvmti_error(jvmti, err, "set env local storage");167delete agent;168} mexit(jvmti, vm_death_lock);169170}171static void JNICALL172thread_start(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)173{174menter(jvmti, vm_death_lock); {175if ( !vm_death_active ) {176get_agent(jvmti)->thread_start(jvmti, env, thread);177}178} mexit(jvmti, vm_death_lock);179}180static void JNICALL181thread_end(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)182{183menter(jvmti, vm_death_lock); {184if ( !vm_death_active ) {185get_agent(jvmti)->thread_end(jvmti, env, thread);186}187} mexit(jvmti, vm_death_lock);188}189static void JNICALL190monitor_contended_enter(jvmtiEnv* jvmti, JNIEnv *env,191jthread thread, jobject object)192{193menter(jvmti, vm_death_lock); {194if ( !vm_death_active ) {195get_agent(jvmti)->monitor_contended_enter(jvmti, env,196thread, object);197}198} mexit(jvmti, vm_death_lock);199}200static void JNICALL201monitor_contended_entered(jvmtiEnv* jvmti, JNIEnv *env,202jthread thread, jobject object)203{204menter(jvmti, vm_death_lock); {205if ( !vm_death_active ) {206get_agent(jvmti)->monitor_contended_entered(jvmti, env,207thread, object);208}209} mexit(jvmti, vm_death_lock);210}211static void JNICALL212monitor_wait(jvmtiEnv* jvmti, JNIEnv *env,213jthread thread, jobject object, jlong timeout)214{215menter(jvmti, vm_death_lock); {216if ( !vm_death_active ) {217get_agent(jvmti)->monitor_wait(jvmti, env, thread,218object, timeout);219}220} mexit(jvmti, vm_death_lock);221}222static void JNICALL223monitor_waited(jvmtiEnv* jvmti, JNIEnv *env,224jthread thread, jobject object, jboolean timed_out)225{226menter(jvmti, vm_death_lock); {227if ( !vm_death_active ) {228get_agent(jvmti)->monitor_waited(jvmti, env, thread,229object, timed_out);230}231} mexit(jvmti, vm_death_lock);232}233static void JNICALL234object_free(jvmtiEnv* jvmti, jlong tag)235{236menter(jvmti, vm_death_lock); {237if ( !vm_death_active ) {238get_agent(jvmti)->object_free(jvmti, tag);239}240} mexit(jvmti, vm_death_lock);241}242243/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */244JNIEXPORT jint JNICALL245Agent_OnLoad(JavaVM *vm, char *options, void *reserved)246{247jvmtiEnv *jvmti;248jint rc;249jvmtiError err;250jvmtiCapabilities capabilities;251jvmtiEventCallbacks callbacks;252253/* Get JVMTI environment */254rc = vm->GetEnv((void **)&jvmti, JVMTI_VERSION);255if (rc != JNI_OK) {256fatal_error("ERROR: Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc);257return -1;258}259260/* Get/Add JVMTI capabilities */261(void)memset(&capabilities, 0, sizeof(capabilities));262capabilities.can_generate_monitor_events = 1;263capabilities.can_get_monitor_info = 1;264capabilities.can_tag_objects = 1;265capabilities.can_generate_object_free_events = 1;266err = jvmti->AddCapabilities(&capabilities);267check_jvmti_error(jvmti, err, "add capabilities");268269/* Set all callbacks and enable VM_INIT event notification */270memset(&callbacks, 0, sizeof(callbacks));271callbacks.VMInit = &vm_init;272callbacks.VMDeath = &vm_death;273callbacks.ThreadStart = &thread_start;274callbacks.ThreadEnd = &thread_end;275callbacks.MonitorContendedEnter = &monitor_contended_enter;276callbacks.MonitorContendedEntered = &monitor_contended_entered;277callbacks.MonitorWait = &monitor_wait;278callbacks.MonitorWaited = &monitor_waited;279callbacks.ObjectFree = &object_free;280err = jvmti->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks));281check_jvmti_error(jvmti, err, "set event callbacks");282err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,283JVMTI_EVENT_VM_INIT, NULL);284check_jvmti_error(jvmti, err, "set event notify");285return 0;286}287288/* Agent_OnUnload() is called last */289JNIEXPORT void JNICALL290Agent_OnUnload(JavaVM *vm)291{292}293294} /* of extern "C" */295296297