blob: e90ad6e9376875c2bb4c490e816651c49cb1bf58 [file] [log] [blame]
/*
* Copyright (c) 2007, 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 "jvmti.h"
#include "jni_tools.h"
#include "agent_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef JNI_ENV_ARG
#ifdef __cplusplus
#define JNI_ENV_ARG(x, y) y
#define JNI_ENV_ARG1(x)
#define JNI_ENV_PTR(x) x
#else
#define JNI_ENV_ARG(x,y) x, y
#define JNI_ENV_ARG1(x) x
#define JNI_ENV_PTR(x) (*x)
#endif
#endif
#define JVMTI_ENV_ARG JNI_ENV_ARG
#define JVMTI_ENV_ARG1 JNI_ENV_ARG1
#define JVMTI_ENV_PTR JNI_ENV_PTR
#define STATUS_FAILED 2
#define PASSED 0
#define JVMTI_ERROR_CHECK(str,res) \
if ( res != JVMTI_ERROR_NONE) { \
printf("%s %d\n" ,str, res); \
return res; \
}
#define JVMTI_ERROR_CHECK_EXPECTED_ERROR(str,res,err) \
if ( res != err) { \
printf("%s unexpected error %d\n", str, res); \
return res; \
}
#define JVMTI_ERROR_CHECK_VOID(str,res) \
if (res != JVMTI_ERROR_NONE) { \
printf("%s %d\n" ,str, res); \
iGlobalStatus = STATUS_FAILED; \
}
#define JVMTI_ERROR_CHECK_EXPECTED_ERROR_VOID(str,res,err) \
if (res != err) { \
printf("%s unexpected error %d\n",str, res); \
iGlobalStatus = STATUS_FAILED; \
}
static jvmtiEnv *jvmti;
static jint iGlobalStatus = PASSED;
static jvmtiCapabilities jvmti_caps;
static jrawMonitorID jraw_monitor;
#define MAX_FRAMES_CNT 30
static jvmtiStackInfo *stack_buf1 = NULL;
static jvmtiStackInfo *stack_buf2 = NULL;
static jthread *thread_list = NULL;
static jvmtiThreadInfo *thread_info = NULL;
static jint threads_count = 0;
#ifdef STATIC_BUILD
JNIEXPORT jint JNICALL Agent_OnLoad_getallstktr001(JavaVM *jvm, char *options, void *reserved) {
return Agent_Initialize(jvm, options, reserved);
}
JNIEXPORT jint JNICALL Agent_OnAttach_getallstktr001(JavaVM *jvm, char *options, void *reserved) {
return Agent_Initialize(jvm, options, reserved);
}
JNIEXPORT jint JNI_OnLoad_getallstktr001(JavaVM *jvm, char *options, void *reserved) {
return JNI_VERSION_1_8;
}
#endif
jint Agent_Initialize(JavaVM * jvm, char *options, void *reserved) {
jint res;
res = JNI_ENV_PTR(jvm)->
GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), JVMTI_VERSION_1_1);
if (res < 0) {
printf("Wrong result of a valid call to GetEnv!\n");
return JNI_ERR;
}
/* Add capabilities */
res = JVMTI_ENV_PTR(jvmti)->GetPotentialCapabilities(JVMTI_ENV_ARG(jvmti, &jvmti_caps));
JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res);
res = JVMTI_ENV_PTR(jvmti)->AddCapabilities(JVMTI_ENV_ARG(jvmti, &jvmti_caps));
JVMTI_ERROR_CHECK("GetPotentialCapabilities returned error", res);
return JNI_OK;
}
JNIEXPORT jint JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_GetResult(
JNIEnv * env, jclass cls)
{
return iGlobalStatus;
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_CreateRawMonitor(
JNIEnv * env, jclass cls)
{
jvmtiError ret;
char sz[128];
sprintf(sz, "Raw-monitor");
ret = JVMTI_ENV_PTR(jvmti)->CreateRawMonitor(JVMTI_ENV_ARG1(jvmti),
sz, &jraw_monitor);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: Raw monitor create %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_RawMonitorEnter(
JNIEnv * env, jclass cls)
{
jvmtiError ret;
ret = JVMTI_ENV_PTR(jvmti)->RawMonitorEnter(JVMTI_ENV_ARG1(jvmti),
jraw_monitor);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: Raw monitor enter %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_RawMonitorExit(
JNIEnv * env, jclass cls)
{
jvmtiError ret;
ret = JVMTI_ENV_PTR(jvmti)->RawMonitorExit(JVMTI_ENV_ARG1(jvmti),
jraw_monitor);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: RawMonitorExit %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
}
void compare_all_frames(int ti, int frames_count,
jvmtiFrameInfo *fr_buf1,
jvmtiFrameInfo *fr_buf2)
{
int fi;
jvmtiFrameInfo *fr1, *fr2;
for (fi = 0; fi < frames_count; fi++) {
fr1 = &fr_buf1[fi];
fr2 = &fr_buf2[fi];
if (fr1->method != fr2->method) {
printf("FAILED: compare frame: thread %d: frame %d: "
"different methods", ti, fi);
iGlobalStatus = STATUS_FAILED;
return;
}
if (fr1->location != fr2->location) {
printf("FAILED: compare frame: thread %d: frame %d: "
"different locations", ti, fi);
iGlobalStatus = STATUS_FAILED;
return;
}
printf("thr #%d: compare frame #%d: fields are the same: "
" method: 0x%p, location: %#"LL"x\n",
ti, fi, fr1->method, fr1->location);
fflush(0);
}
}
void compare_one_stack_trace(int ti,
jvmtiStackInfo *stk1,
jvmtiStackInfo *stk2,
jvmtiThreadInfo *thr_info)
{
static const char* TEST_THREAD_NAME_PREFIX = "getallstktr001-";
size_t PFX_LEN = strlen(TEST_THREAD_NAME_PREFIX);
if (thr_info->name != NULL) {
printf("compare stack #%d: thread: %s\n", ti, thr_info->name);
} else {
printf("compare stack #%d: thread is NULL\n", ti);
return;
}
if (strlen(thr_info->name) < PFX_LEN ||
strncmp(thr_info->name, TEST_THREAD_NAME_PREFIX, PFX_LEN) != 0)
{
printf("compare stack #%d: %s isn't tested thread - skip it\n",
ti, thr_info->name);
return;
}
if (stk1->state != stk2->state) {
printf("FAILED: compare stack #%d: different states: "
"st1: %d, st2: %d\n",
ti, stk1->state, stk2->state);
iGlobalStatus = STATUS_FAILED;
return;
}
if (stk1->frame_count != stk2->frame_count) {
printf("FAILED: compare stack #%d: different frame_count: "
"cnt1: %d, cnt2: %d\n",
ti, stk1->frame_count, stk2->frame_count);
iGlobalStatus = STATUS_FAILED;
return;
}
printf("compare stack #%d: fields are the same: "
" jthread: 0x%p, state: %d, frame_count: %d\n",
ti, stk1->thread, stk1->state, stk1->frame_count);
fflush(0);
compare_all_frames(ti,
stk1->frame_count,
stk1->frame_buffer,
stk2->frame_buffer);
}
void compare_all_stack_traces(int thr_count,
jvmtiStackInfo *stk_buf1,
jvmtiStackInfo *stk_buf2,
jvmtiThreadInfo *thr_info)
{
int ti;
for (ti = 0; ti < thr_count; ti++) {
compare_one_stack_trace(ti, &stk_buf1[ti], &stk_buf2[ti], &thr_info[ti]);
}
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_GetAllStackTraces(
JNIEnv * env, jclass cls)
{
jvmtiError ret;
int ti;
ret = JVMTI_ENV_PTR(jvmti)->GetAllStackTraces(JVMTI_ENV_ARG1(jvmti),
MAX_FRAMES_CNT,
&stack_buf1,
&threads_count);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: GetAllStackTraces %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
ret = JVMTI_ENV_PTR(jvmti)->Allocate(JVMTI_ENV_ARG1(jvmti),
sizeof(jthread) * threads_count,
(unsigned char**)&thread_list);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: Allocate failed with %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
for (ti = 0; ti < threads_count; ti++) {
thread_list[ti] =
(jthread)JNI_ENV_PTR(env)->NewGlobalRef(
JNI_ENV_ARG(env, stack_buf1[ti].thread));
}
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_GetThreadsInfo(
JNIEnv * env, jclass cls)
{
jvmtiError ret;
int ti;
ret = JVMTI_ENV_PTR(jvmti)->Allocate(JVMTI_ENV_ARG1(jvmti),
sizeof(jvmtiThreadInfo) * threads_count,
(unsigned char**)&thread_info);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: Allocate failed with %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
for (ti = 0; ti < threads_count; ti++) {
ret = JVMTI_ENV_PTR(jvmti)->GetThreadInfo(JVMTI_ENV_ARG1(jvmti),
thread_list[ti],
&thread_info[ti]);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: GetThreadInfo %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
printf("GetThreadInfo %d: thread: %s\n", ti, thread_info[ti].name);
fflush(0);
}
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_GetThreadListStackTraces(
JNIEnv * env, jclass cls)
{
jvmtiError ret;
ret = JVMTI_ENV_PTR(jvmti)->GetThreadListStackTraces(
JVMTI_ENV_ARG1(jvmti),
threads_count,
thread_list,
MAX_FRAMES_CNT,
&stack_buf2);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: GetThreadListStackTraces %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_ForceGC(
JNIEnv * env, jclass cls)
{
jvmtiError ret;
ret = JVMTI_ENV_PTR(jvmti)->ForceGarbageCollection(JVMTI_ENV_ARG1(jvmti));
if (ret != JVMTI_ERROR_NONE) {
printf("Error: ForceGarbageCollection %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_CompareStackTraces(
JNIEnv * env, jclass cls)
{
compare_all_stack_traces(threads_count, stack_buf1, stack_buf2, thread_info);
}
JNIEXPORT void JNICALL
Java_nsk_jvmti_unit_GetAllStackTraces_getallstktr001_DeallocateBuffers(
JNIEnv * env, jclass cls)
{
jvmtiError ret;
ret = JVMTI_ENV_PTR(jvmti)->Deallocate(JVMTI_ENV_ARG1(jvmti),
(unsigned char *)stack_buf1);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: Deallocate stack_buf1 failed with %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
ret = JVMTI_ENV_PTR(jvmti)->Deallocate(JVMTI_ENV_ARG1(jvmti),
(unsigned char *)stack_buf2);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: Deallocate stack_buf2 failed with %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
ret = JVMTI_ENV_PTR(jvmti)->Deallocate(JVMTI_ENV_ARG1(jvmti),
(unsigned char *)thread_info);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: Deallocate thread_info failed with %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
ret = JVMTI_ENV_PTR(jvmti)->Deallocate(JVMTI_ENV_ARG1(jvmti),
(unsigned char *)thread_list);
if (ret != JVMTI_ERROR_NONE) {
printf("Error: Deallocate thread_list failed with %d \n", ret);
iGlobalStatus = STATUS_FAILED;
}
}
#ifdef __cplusplus
}
#endif