Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/waiters/Agent.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#include <stdio.h>41#include <stdlib.h>42#include <string.h>43#include <stddef.h>4445#include "jni.h"46#include "jvmti.h"4748#include "agent_util.h"4950#include "Monitor.hpp"51#include "Thread.hpp"52#include "Agent.hpp"5354/* Implementation of the Agent class */5556/* Given a jvmtiEnv* and jthread, find the Thread instance */57Thread *58Agent::get_thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)59{60jvmtiError err;61Thread *t;6263/* This should always be in the Thread Local Storage */64t = NULL;65err = jvmti->GetThreadLocalStorage(thread, (void**)&t);66check_jvmti_error(jvmti, err, "get thread local storage");67if ( t == NULL ) {68/* This jthread has never been seen before? */69stdout_message("WARNING: Never before seen jthread?\n");70t = new Thread(jvmti, env, thread);71err = jvmti->SetThreadLocalStorage(thread, (const void*)t);72check_jvmti_error(jvmti, err, "set thread local storage");73}74return t;75}7677/* Given a jvmtiEnv* and jobject, find the Monitor instance or create one */78Monitor *79Agent::get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object)80{81jvmtiError err;82Monitor *m;83jlong tag;8485m = NULL;86tag = (jlong)0;87err = jvmti->GetTag(object, &tag);88check_jvmti_error(jvmti, err, "get tag");89/*LINTED*/90m = (Monitor *)(void *)(ptrdiff_t)tag;91if ( m == NULL ) {92m = new Monitor(jvmti, env, object);93/* Save monitor on list */94if (monitor_count == monitor_list_size) {95monitor_list_size += monitor_list_grow_size;96monitor_list = (Monitor**)realloc((void*)monitor_list,97(monitor_list_size)*(int)sizeof(Monitor*));98}99monitor_list[monitor_count] = m;100m->set_slot(monitor_count);101monitor_count++;102/*LINTED*/103tag = (jlong)(ptrdiff_t)(void *)m;104err = jvmti->SetTag(object, tag);105check_jvmti_error(jvmti, err, "set tag");106}107return m;108}109110/* VM initialization and VM death calls to Agent */111Agent::Agent(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)112{113jvmtiError err;114115stdout_message("Agent created..\n");116stdout_message("VMInit...\n");117/* Start monitor list */118monitor_count = 0;119monitor_list_size = initial_monitor_list_size;120monitor_list = (Monitor**)121malloc(monitor_list_size*(int)sizeof(Monitor*));122}123124Agent::~Agent()125{126stdout_message("Agent reclaimed..\n");127}128129void Agent::vm_death(jvmtiEnv *jvmti, JNIEnv *env)130{131jvmtiError err;132133/* Delete all Monitors we allocated */134for ( int i = 0; i < (int)monitor_count; i++ ) {135delete monitor_list[i];136}137free(monitor_list);138/* Print death message */139stdout_message("VMDeath...\n");140}141142/* Thread start event, setup a new thread */143void Agent::thread_start(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)144{145jvmtiError err;146Thread *t;147148/* Allocate a new Thread instance, put it in the Thread Local149* Storage for easy access later.150*/151t = new Thread(jvmti, env, thread);152err = jvmti->SetThreadLocalStorage(thread, (const void*)t);153check_jvmti_error(jvmti, err, "set thread local storage");154}155156157/* Thread end event, we need to reclaim the space */158void Agent::thread_end(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)159{160jvmtiError err;161Thread *t;162163/* Find the thread */164t = get_thread(jvmti, env, thread);165166/* Clear out the Thread Local Storage */167err = jvmti->SetThreadLocalStorage(thread, (const void*)NULL);168check_jvmti_error(jvmti, err, "set thread local storage");169170/* Reclaim the C++ object space */171delete t;172}173174/* Monitor contention begins for a thread. */175void Agent::monitor_contended_enter(jvmtiEnv* jvmti, JNIEnv *env,176jthread thread, jobject object)177{178get_monitor(jvmti, env, object)->contended();179get_thread(jvmti, env, thread)->180monitor_contended_enter(jvmti, env, thread, object);181}182183/* Monitor contention ends for a thread. */184void Agent::monitor_contended_entered(jvmtiEnv* jvmti, JNIEnv *env,185jthread thread, jobject object)186{187/* Do nothing for now */188}189190/* Monitor wait begins for a thread. */191void Agent::monitor_wait(jvmtiEnv* jvmti, JNIEnv *env,192jthread thread, jobject object, jlong timeout)193{194get_monitor(jvmti, env, object)->waited();195get_thread(jvmti, env, thread)->196monitor_wait(jvmti, env, thread, object, timeout);197}198199/* Monitor wait ends for a thread. */200void Agent::monitor_waited(jvmtiEnv* jvmti, JNIEnv *env,201jthread thread, jobject object, jboolean timed_out)202{203if ( timed_out ) {204get_monitor(jvmti, env, object)->timeout();205}206get_thread(jvmti, env, thread)->207monitor_waited(jvmti, env, thread, object, timed_out);208}209210/* A tagged object has been freed */211void Agent::object_free(jvmtiEnv* jvmti, jlong tag)212{213/* We just cast the tag to a C++ pointer and delete it.214* we know it can only be a Monitor *.215*/216Monitor *m;217/*LINTED*/218m = (Monitor *)(ptrdiff_t)tag;219if (monitor_count > 1) {220/* Move the last element to this Monitor's slot */221int slot = m->get_slot();222Monitor *last = monitor_list[monitor_count-1];223monitor_list[slot] = last;224last->set_slot(slot);225}226monitor_count--;227delete m;228}229230231