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