test/runtime/RedefineTests/libRedefineDoubleDelete.c

changeset 9748
628176d22495
equal deleted inserted replaced
9747:760b28d87178 9748:628176d22495
1 /*
2 * Copyright (c) 2017, 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
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 #ifndef JNI_ENV_ARG
33
34 #ifdef __cplusplus
35 #define JNI_ENV_ARG(x, y) y
36 #define JNI_ENV_PTR(x) x
37 #else
38 #define JNI_ENV_ARG(x,y) x, y
39 #define JNI_ENV_PTR(x) (*x)
40 #endif
41
42 #endif
43
44 #define TranslateError(err) "JVMTI error"
45
46 static jvmtiEnv *jvmti = NULL;
47
48 static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
49
50 JNIEXPORT
51 jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
52 return Agent_Initialize(jvm, options, reserved);
53 }
54
55 JNIEXPORT
56 jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
57 return Agent_Initialize(jvm, options, reserved);
58 }
59
60 JNIEXPORT
61 jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
62 return JNI_VERSION_1_8;
63 }
64
65
66 static jint newClassDataLen = 0;
67 static unsigned char* newClassData = NULL;
68
69 static jint
70 getBytecodes(jvmtiEnv *jvmti_env,
71 jint class_data_len, const unsigned char* class_data) {
72 int i;
73 jint res;
74
75 newClassDataLen = class_data_len;
76 res = (*jvmti_env)->Allocate(jvmti_env, newClassDataLen, &newClassData);
77 if (res != JNI_OK) {
78 printf(" Unable to allocate bytes\n");
79 return JNI_ERR;
80 }
81 for (i = 0; i < newClassDataLen; i++) {
82 newClassData[i] = class_data[i];
83 // Rewrite oo in class to aa
84 if (i > 0 && class_data[i] == 'o' && class_data[i-1] == 'o') {
85 newClassData[i] = newClassData[i-1] = 'a';
86 }
87 }
88 printf(" ... copied bytecode: %d bytes\n", (int)newClassDataLen);
89 return JNI_OK;
90 }
91
92
93 static void JNICALL
94 Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
95 jclass class_being_redefined,
96 jobject loader, const char* name, jobject protection_domain,
97 jint class_data_len, const unsigned char* class_data,
98 jint *new_class_data_len, unsigned char** new_class_data) {
99 if (name != NULL && strcmp(name, "RedefineDoubleDelete$B") == 0) {
100 if (newClassData == NULL) {
101 jint res = getBytecodes(jvmti_env, class_data_len, class_data);
102 if (res == JNI_ERR) {
103 printf(">>> ClassFileLoadHook event: class name %s FAILED\n", name);
104 return;
105 }
106 // Only change for first CFLH event.
107 *new_class_data_len = newClassDataLen;
108 *new_class_data = newClassData;
109 }
110 printf(">>> ClassFileLoadHook event: class name %s\n", name);
111 }
112 }
113
114 static
115 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
116 jint res, size;
117 jvmtiCapabilities caps;
118 jvmtiEventCallbacks callbacks;
119 jvmtiError err;
120
121 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
122 JVMTI_VERSION_1_2);
123 if (res != JNI_OK || jvmti == NULL) {
124 printf(" Error: wrong result of a valid call to GetEnv!\n");
125 return JNI_ERR;
126 }
127
128 printf("Enabling following capabilities: can_generate_all_class_hook_events, "
129 "can_retransform_classes, can_redefine_classes");
130 memset(&caps, 0, sizeof(caps));
131 caps.can_generate_all_class_hook_events = 1;
132 caps.can_retransform_classes = 1;
133 caps.can_redefine_classes = 1;
134 printf("\n");
135
136 err = (*jvmti)->AddCapabilities(jvmti, &caps);
137 if (err != JVMTI_ERROR_NONE) {
138 printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
139 return JNI_ERR;
140 }
141
142 size = (jint)sizeof(callbacks);
143
144 memset(&callbacks, 0, sizeof(callbacks));
145 callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
146
147 err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
148 if (err != JVMTI_ERROR_NONE) {
149 printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
150 return JNI_ERR;
151 }
152
153 err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
154 if (err != JVMTI_ERROR_NONE) {
155 printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
156 return JNI_ERR;
157 }
158
159 return JNI_OK;
160 }
161
162 #ifdef __cplusplus
163 }
164 #endif

mercurial