1 /*
2 * Copyright (c) 2004, 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 <stdlib.h>
26 #include <string.h>
27
28 #include <jvmti.h>
29 #include "agent_common.h"
30
31 #include "nsk_tools.h"
32 #include "native_thread.h"
33 #include "JVMTITools.h"
34 #include "jvmti_tools.h"
35
36 extern "C" {
37
38 #define PASSED 0
39 #define STATUS_FAILED 2
40
41 #define MAX_ATTEMPTS 15
42
43 static const char *expHSMethod = "redefclass029HotMethod";
44 static const char *expHSSignature = "(I)V";
45
46 #define EVENTS_COUNT 2
47 static jvmtiEvent eventsList[EVENTS_COUNT] = {
48 JVMTI_EVENT_COMPILED_METHOD_LOAD,
49 JVMTI_EVENT_COMPILED_METHOD_UNLOAD
50 };
51
52 static jvmtiEnv *jvmti = NULL;
53 static jlong timeout = 0;
54 static volatile int fire = 0; /* CompiledMethodLoad received for hotspot method */
55 static jmethodID hsMethodID; /* hotspot method ID */
56
57 static volatile int enteredHotMethod = 0; /* "hot" method is entered */
58
59 static jint bytesCount; /* number of bytes of a redefining class */
60 static jbyte *clsBytes; /* bytes defining a redefining class */
61
62 /** pass info about redefinition to Java **/
Java_nsk_jvmti_RedefineClasses_redefclass029_isRedefinitionOccurred(JNIEnv * jni_env,jclass cls)63 JNIEXPORT jboolean JNICALL Java_nsk_jvmti_RedefineClasses_redefclass029_isRedefinitionOccurred
64 (JNIEnv *jni_env, jclass cls)
65 {
66 if (fire == 1) {
67 NSK_DISPLAY0("isRedefinitionOccurred is called: fired!\n");
68 return JNI_TRUE;
69 } else {
70 return JNI_FALSE;
71 }
72 }
73
74 /** notify native agent from Java when "hot" method is executed **/
Java_nsk_jvmti_RedefineClasses_redefclass029_notifyNativeAgent(JNIEnv * jni_env,jclass cls)75 JNIEXPORT void JNICALL Java_nsk_jvmti_RedefineClasses_redefclass029_notifyNativeAgent
76 (JNIEnv *jni_env, jclass cls)
77 {
78 if (enteredHotMethod == 0) {
79 NSK_DISPLAY0("notifyNativeAgent is called\n");
80 enteredHotMethod = 1;
81 }
82 }
83
Java_nsk_jvmti_RedefineClasses_redefclass029_storeClassBytes(JNIEnv * jni_env,jclass cls,jbyteArray classBytes)84 JNIEXPORT void JNICALL Java_nsk_jvmti_RedefineClasses_redefclass029_storeClassBytes
85 (JNIEnv *jni_env, jclass cls, jbyteArray classBytes) {
86 jboolean isCopy;
87
88 bytesCount = jni_env->GetArrayLength(classBytes);
89 clsBytes =
90 jni_env->GetByteArrayElements(classBytes, &isCopy);
91 }
92
93 /** callback functions **/
94 void JNICALL
CompiledMethodLoad(jvmtiEnv * jvmti_env,jmethodID method,jint code_size,const void * code_addr,jint map_length,const jvmtiAddrLocationMap * map,const void * compile_info)95 CompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, jint code_size,
96 const void* code_addr, jint map_length, const jvmtiAddrLocationMap* map,
97 const void* compile_info) {
98 char *name;
99 char *sig;
100
101 NSK_DISPLAY0("CompiledMethodLoad event received for:\n");
102 if (!NSK_JVMTI_VERIFY(jvmti_env->GetMethodName(method, &name, &sig, NULL))) {
103 nsk_jvmti_setFailStatus();
104 return;
105 }
106 NSK_DISPLAY5("\tmethod: name=\"%s\" signature=\"%s\"\n"
107 "\tcompiled code size=%d\n"
108 "\tstarting native address=0x%p\n"
109 "\tnumber of address location map entries=%d\n",
110 name, sig, code_size, code_addr, map_length);
111
112 if ((strcmp(name, expHSMethod) == 0) &&
113 (strcmp(sig, expHSSignature) == 0)) {
114 NSK_DISPLAY0("CompiledMethodLoad: a tested hotspot method found\n");
115
116 // CR 6604375: check whether "hot" method was entered
117 if (enteredHotMethod) {
118 hsMethodID = method;
119 fire = 1;
120 } else {
121 NSK_DISPLAY0("Compilation occured before method execution. Ignoring.\n");
122 }
123 }
124 }
125
126 JNIEXPORT void JNICALL
CompiledMethodUnload(jvmtiEnv * jvmti_env,jmethodID method,const void * code_addr)127 CompiledMethodUnload(jvmtiEnv* jvmti_env, jmethodID method,
128 const void* code_addr) {
129 char *name;
130 char *sig;
131 jvmtiError err;
132
133 NSK_DISPLAY0("CompiledMethodUnload event received\n");
134 // Check for the case that the class has been unloaded
135 err = jvmti_env->GetMethodName(method, &name, &sig, NULL);
136 if (err == JVMTI_ERROR_NONE) {
137 NSK_DISPLAY3("for: \tmethod: name=\"%s\" signature=\"%s\"\n\tnative address=0x%p\n",
138 name, sig, code_addr);
139 jvmti_env->Deallocate((unsigned char*)name);
140 jvmti_env->Deallocate((unsigned char*)sig);
141 }
142 }
143 /************************/
144
145 /** agent's procedure **/
146 static void JNICALL
agentProc(jvmtiEnv * jvmti_env,JNIEnv * jni_env,void * arg)147 agentProc(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg) {
148 int tries = 0;
149 jclass decl_cls;
150 char *cls_sig;
151 jvmtiClassDefinition classDef;
152
153 /* testing sync */
154 NSK_DISPLAY1("agentProc: waiting for the debuggee start for %d msecs...\n\n",
155 (int) timeout);
156 if (!nsk_jvmti_waitForSync(timeout))
157 return;
158 NSK_DISPLAY0("agentProc: resuming the debuggee ...\n\n");
159 if (!nsk_jvmti_resumeSync())
160 return;
161
162 /* at first, send all generated CompiledMethodLoad events */
163 NSK_DISPLAY0("agentProc: sending all generated CompiledMethodLoad events ...\n\n");
164 if (!NSK_JVMTI_VERIFY(jvmti->GenerateEvents(JVMTI_EVENT_COMPILED_METHOD_LOAD))) {
165 nsk_jvmti_setFailStatus();
166 nsk_jvmti_resumeSync();
167 return;
168 }
169
170 NSK_DISPLAY0("agentProc: waiting for hotspot method compilation...\n\n");
171 do {
172 THREAD_sleep(1);
173 tries++;
174 if (tries > MAX_ATTEMPTS) {
175 printf("WARNING: CompiledMethodLoad event is still not received for \"%s\" after %d attempts\n"
176 "\tThe test has no results\n\n",
177 expHSMethod, MAX_ATTEMPTS);
178 nsk_jvmti_resumeSync();
179 exit(95 + PASSED);
180 }
181 } while (fire == 0);
182
183 NSK_DISPLAY0("agentProc: hotspot method compiled\n\n");
184
185 if (!NSK_JVMTI_VERIFY(jvmti_env->GetMethodDeclaringClass(hsMethodID, &decl_cls))) {
186 nsk_jvmti_setFailStatus();
187 nsk_jvmti_resumeSync();
188 return;
189 }
190 if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(decl_cls, &cls_sig, NULL))) {
191 nsk_jvmti_setFailStatus();
192 nsk_jvmti_resumeSync();
193 return;
194 } else {
195 NSK_DISPLAY1("agentProc: hotspot method class signature: \"%s\"\n\n",
196 cls_sig);
197 }
198
199 /* fill the structure jvmtiClassDefinition */
200 classDef.klass = decl_cls;
201 classDef.class_byte_count = bytesCount;
202 classDef.class_bytes = (unsigned char*) clsBytes;
203
204 NSK_DISPLAY1("agentProc: >>>>>>>> Invoke RedefineClasses():\n"
205 "\tnew class byte count=%d\n",
206 classDef.class_byte_count);
207 if (!NSK_JVMTI_VERIFY(jvmti->RedefineClasses(1, &classDef))) {
208 nsk_jvmti_setFailStatus();
209 nsk_jvmti_resumeSync();
210 return;
211 }
212 NSK_DISPLAY0("agentProc: <<<<<<<< RedefineClasses() is successfully done\n");
213
214 /* testing sync */
215 NSK_DISPLAY1("agentProc: waiting for the debuggee finish for %d msecs...\n\n",
216 (int) timeout);
217 if (!nsk_jvmti_waitForSync(timeout))
218 return;
219 NSK_DISPLAY0("agentProc: final resuming of the debuggee ...\n\n");
220 if (!nsk_jvmti_resumeSync())
221 return;
222
223 NSK_DISPLAY0("agentProc: finished\n\n");
224 }
225
226 #ifdef STATIC_BUILD
Agent_OnLoad_redefclass029(JavaVM * jvm,char * options,void * reserved)227 JNIEXPORT jint JNICALL Agent_OnLoad_redefclass029(JavaVM *jvm, char *options, void *reserved) {
228 return Agent_Initialize(jvm, options, reserved);
229 }
Agent_OnAttach_redefclass029(JavaVM * jvm,char * options,void * reserved)230 JNIEXPORT jint JNICALL Agent_OnAttach_redefclass029(JavaVM *jvm, char *options, void *reserved) {
231 return Agent_Initialize(jvm, options, reserved);
232 }
JNI_OnLoad_redefclass029(JavaVM * jvm,char * options,void * reserved)233 JNIEXPORT jint JNI_OnLoad_redefclass029(JavaVM *jvm, char *options, void *reserved) {
234 return JNI_VERSION_1_8;
235 }
236 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)237 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
238 jvmtiCapabilities caps;
239 jvmtiEventCallbacks callbacks;
240
241 /* init framework and parse options */
242 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
243 return JNI_ERR;
244
245 /* obtain WAITTIME parameter */
246 timeout = nsk_jvmti_getWaitTime() * 60000;
247 NSK_DISPLAY1("waittime=%d msecs\n", (int) timeout);
248
249 /* create JVMTI environment */
250 if (!NSK_VERIFY((jvmti =
251 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
252 return JNI_ERR;
253
254 /* add required capabilities */
255 memset(&caps, 0, sizeof(jvmtiCapabilities));
256 caps.can_generate_compiled_method_load_events = 1;
257 caps.can_redefine_classes = 1;
258 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
259 return JNI_ERR;
260
261 /* set event callback */
262 NSK_DISPLAY0("setting event callbacks ...\n");
263 (void) memset(&callbacks, 0, sizeof(callbacks));
264 callbacks.CompiledMethodLoad = &CompiledMethodLoad;
265 callbacks.CompiledMethodUnload = &CompiledMethodUnload;
266 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks))))
267 return JNI_ERR;
268
269 NSK_DISPLAY0("setting event callbacks done\nenabling events ...\n");
270 if (!nsk_jvmti_enableEvents(JVMTI_ENABLE, EVENTS_COUNT,
271 eventsList, NULL))
272 return JNI_ERR;
273 NSK_DISPLAY0("enabling the events done\n\n");
274
275 /* register agent proc */
276 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
277 return JNI_ERR;
278
279 return JNI_OK;
280 }
281
282 }
283