1 /* 2 * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include <stdio.h> 25 #include <string.h> 26 #include "jvmti.h" 27 #include "agent_common.h" 28 #include "JVMTITools.h" 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 #ifndef JNI_ENV_ARG 35 36 #ifdef __cplusplus 37 #define JNI_ENV_ARG(x, y) y 38 #define JNI_ENV_PTR(x) x 39 #else 40 #define JNI_ENV_ARG(x,y) x, y 41 #define JNI_ENV_PTR(x) (*x) 42 #endif 43 44 #endif 45 46 #define PASSED 0 47 #define STATUS_FAILED 2 48 49 static JavaVM *jvm_ins; 50 static jvmtiEnv *jvmti = NULL; 51 static jvmtiEventCallbacks callbacks; 52 static jint result = PASSED; 53 static jboolean printdump = JNI_FALSE; 54 static jboolean agent_was_started = JNI_FALSE; 55 static jboolean done = JNI_FALSE; 56 57 58 jthread jthr(JNIEnv *env) { 59 jclass thrClass; 60 jmethodID cid; 61 jthread res; 62 63 thrClass = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, "java/lang/Thread")); 64 cid = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, thrClass), "<init>", "()V"); 65 res = JNI_ENV_PTR(env)->NewObject(JNI_ENV_ARG(env, thrClass), cid); 66 return res; 67 } 68 69 void JNICALL agent_start(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void *p) { 70 JNIEnv *env; 71 72 if (jvmti_env != jvmti) { 73 printf("(agent_start) JVMTI envs don't match\n"); 74 result = STATUS_FAILED; 75 } 76 77 JNI_ENV_PTR(jvm_ins)->GetEnv(JNI_ENV_ARG(jvm_ins, (void **) &env), 78 JNI_VERSION_1_2); 79 if (jni_env != env) { 80 printf("(agent_start) JNI envs don't match\n"); 81 result = STATUS_FAILED; 82 } 83 84 if ((size_t)p != 12345) { 85 printf("(agent_start) args don't match\n"); 86 result = STATUS_FAILED; 87 } 88 done = JNI_TRUE; 89 } 90 91 92 93 void JNICALL vm_init(jvmtiEnv* jvmti_env, JNIEnv *env, jthread thread) { 94 jvmtiError err; 95 96 if (!agent_was_started) { 97 agent_was_started = JNI_TRUE; 98 99 err = jvmti->RunAgentThread(jthr(env), agent_start, 100 (void *)999, JVMTI_THREAD_MAX_PRIORITY+1); 101 if (err != JVMTI_ERROR_INVALID_PRIORITY) { 102 printf("(RunAgentThread#1) expected JVMTI_ERROR_INVALID_PRIORITY got error: %s (%d)\n", 103 TranslateError(err), err); 104 result = STATUS_FAILED; 105 } 106 err = jvmti->RunAgentThread(jthr(env), agent_start, 107 (void *)999, JVMTI_THREAD_MIN_PRIORITY-1); 108 if (err != JVMTI_ERROR_INVALID_PRIORITY) { 109 printf("(RunAgentThread#1) expected JVMTI_ERROR_INVALID_PRIORITY got error: %s (%d)\n", 110 TranslateError(err), err); 111 result = STATUS_FAILED; 112 } 113 err = jvmti->RunAgentThread(jthr(env), agent_start, 114 (void *)12345, JVMTI_THREAD_NORM_PRIORITY); 115 if (err != JVMTI_ERROR_NONE) { 116 printf("(RunAgentThread#2) unexpected error: %s (%d)\n", 117 TranslateError(err), err); 118 result = STATUS_FAILED; 119 } 120 } 121 } 122 123 #ifdef STATIC_BUILD 124 JNIEXPORT jint JNICALL Agent_OnLoad_agentthr(JavaVM *jvm, char *options, void *reserved) { 125 return Agent_Initialize(jvm, options, reserved); 126 } 127 JNIEXPORT jint JNICALL Agent_OnAttach_agentthr(JavaVM *jvm, char *options, void *reserved) { 128 return Agent_Initialize(jvm, options, reserved); 129 } 130 JNIEXPORT jint JNI_OnLoad_agentthr(JavaVM *jvm, char *options, void *reserved) { 131 return JNI_VERSION_1_8; 132 } 133 #endif 134 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 135 jvmtiError err; 136 jint res; 137 138 if (options != NULL && strcmp(options, "printdump") == 0) { 139 printdump = JNI_TRUE; 140 } 141 142 jvm_ins = jvm; 143 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), 144 JVMTI_VERSION_1_1); 145 if (res != JNI_OK || jvmti == NULL) { 146 printf("Wrong result of a valid call to GetEnv!\n"); 147 return JNI_ERR; 148 } 149 150 callbacks.VMInit = &vm_init; 151 err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)); 152 if (err != JVMTI_ERROR_NONE) { 153 printf("(SetEventCallbacks) unexpected error: %s (%d)\n", 154 TranslateError(err), err); 155 return JNI_ERR; 156 } 157 158 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); 159 if (err != JVMTI_ERROR_NONE) { 160 printf("Failed to enable JVMTI_EVENT_THREAD_START: %s (%d)\n", 161 TranslateError(err), err); 162 return JNI_ERR; 163 } 164 165 return JNI_OK; 166 } 167 168 JNIEXPORT jboolean JNICALL 169 Java_nsk_jvmti_unit_agentthr_isOver(JNIEnv *env, jclass cls) { 170 return done; 171 } 172 173 JNIEXPORT jint JNICALL 174 Java_nsk_jvmti_unit_agentthr_getRes(JNIEnv *env, jclass cls) { 175 if (!done) { 176 printf("agent thread has not completed\n"); 177 result = STATUS_FAILED; 178 } 179 return result; 180 } 181 182 #ifdef __cplusplus 183 } 184 #endif