test/runtime/RedefineTests/libRedefineDoubleDelete.c

Thu, 12 Sep 2019 15:15:22 -0400

author
zgu
date
Thu, 12 Sep 2019 15:15:22 -0400
changeset 9748
628176d22495
permissions
-rw-r--r--

8178870: instrumentation.retransformClasses cause coredump
Summary: Don't double-free cached class bytes on redefinition loading failure.
Reviewed-by: sspitsyn, jiangli

zgu@9748 1 /*
zgu@9748 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
zgu@9748 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
zgu@9748 4 *
zgu@9748 5 * This code is free software; you can redistribute it and/or modify it
zgu@9748 6 * under the terms of the GNU General Public License version 2 only, as
zgu@9748 7 * published by the Free Software Foundation.
zgu@9748 8 *
zgu@9748 9 * This code is distributed in the hope that it will be useful, but WITHOUT
zgu@9748 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
zgu@9748 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
zgu@9748 12 * version 2 for more details (a copy is included in the LICENSE file that
zgu@9748 13 * accompanied this code).
zgu@9748 14 *
zgu@9748 15 * You should have received a copy of the GNU General Public License version
zgu@9748 16 * 2 along with this work; if not, write to the Free Software Foundation,
zgu@9748 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
zgu@9748 18 *
zgu@9748 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
zgu@9748 20 * or visit www.oracle.com if you need additional information or have any
zgu@9748 21 * questions.
zgu@9748 22 */
zgu@9748 23
zgu@9748 24 #include <stdio.h>
zgu@9748 25 #include <string.h>
zgu@9748 26 #include "jvmti.h"
zgu@9748 27
zgu@9748 28 #ifdef __cplusplus
zgu@9748 29 extern "C" {
zgu@9748 30 #endif
zgu@9748 31
zgu@9748 32 #ifndef JNI_ENV_ARG
zgu@9748 33
zgu@9748 34 #ifdef __cplusplus
zgu@9748 35 #define JNI_ENV_ARG(x, y) y
zgu@9748 36 #define JNI_ENV_PTR(x) x
zgu@9748 37 #else
zgu@9748 38 #define JNI_ENV_ARG(x,y) x, y
zgu@9748 39 #define JNI_ENV_PTR(x) (*x)
zgu@9748 40 #endif
zgu@9748 41
zgu@9748 42 #endif
zgu@9748 43
zgu@9748 44 #define TranslateError(err) "JVMTI error"
zgu@9748 45
zgu@9748 46 static jvmtiEnv *jvmti = NULL;
zgu@9748 47
zgu@9748 48 static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
zgu@9748 49
zgu@9748 50 JNIEXPORT
zgu@9748 51 jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
zgu@9748 52 return Agent_Initialize(jvm, options, reserved);
zgu@9748 53 }
zgu@9748 54
zgu@9748 55 JNIEXPORT
zgu@9748 56 jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
zgu@9748 57 return Agent_Initialize(jvm, options, reserved);
zgu@9748 58 }
zgu@9748 59
zgu@9748 60 JNIEXPORT
zgu@9748 61 jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
zgu@9748 62 return JNI_VERSION_1_8;
zgu@9748 63 }
zgu@9748 64
zgu@9748 65
zgu@9748 66 static jint newClassDataLen = 0;
zgu@9748 67 static unsigned char* newClassData = NULL;
zgu@9748 68
zgu@9748 69 static jint
zgu@9748 70 getBytecodes(jvmtiEnv *jvmti_env,
zgu@9748 71 jint class_data_len, const unsigned char* class_data) {
zgu@9748 72 int i;
zgu@9748 73 jint res;
zgu@9748 74
zgu@9748 75 newClassDataLen = class_data_len;
zgu@9748 76 res = (*jvmti_env)->Allocate(jvmti_env, newClassDataLen, &newClassData);
zgu@9748 77 if (res != JNI_OK) {
zgu@9748 78 printf(" Unable to allocate bytes\n");
zgu@9748 79 return JNI_ERR;
zgu@9748 80 }
zgu@9748 81 for (i = 0; i < newClassDataLen; i++) {
zgu@9748 82 newClassData[i] = class_data[i];
zgu@9748 83 // Rewrite oo in class to aa
zgu@9748 84 if (i > 0 && class_data[i] == 'o' && class_data[i-1] == 'o') {
zgu@9748 85 newClassData[i] = newClassData[i-1] = 'a';
zgu@9748 86 }
zgu@9748 87 }
zgu@9748 88 printf(" ... copied bytecode: %d bytes\n", (int)newClassDataLen);
zgu@9748 89 return JNI_OK;
zgu@9748 90 }
zgu@9748 91
zgu@9748 92
zgu@9748 93 static void JNICALL
zgu@9748 94 Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
zgu@9748 95 jclass class_being_redefined,
zgu@9748 96 jobject loader, const char* name, jobject protection_domain,
zgu@9748 97 jint class_data_len, const unsigned char* class_data,
zgu@9748 98 jint *new_class_data_len, unsigned char** new_class_data) {
zgu@9748 99 if (name != NULL && strcmp(name, "RedefineDoubleDelete$B") == 0) {
zgu@9748 100 if (newClassData == NULL) {
zgu@9748 101 jint res = getBytecodes(jvmti_env, class_data_len, class_data);
zgu@9748 102 if (res == JNI_ERR) {
zgu@9748 103 printf(">>> ClassFileLoadHook event: class name %s FAILED\n", name);
zgu@9748 104 return;
zgu@9748 105 }
zgu@9748 106 // Only change for first CFLH event.
zgu@9748 107 *new_class_data_len = newClassDataLen;
zgu@9748 108 *new_class_data = newClassData;
zgu@9748 109 }
zgu@9748 110 printf(">>> ClassFileLoadHook event: class name %s\n", name);
zgu@9748 111 }
zgu@9748 112 }
zgu@9748 113
zgu@9748 114 static
zgu@9748 115 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
zgu@9748 116 jint res, size;
zgu@9748 117 jvmtiCapabilities caps;
zgu@9748 118 jvmtiEventCallbacks callbacks;
zgu@9748 119 jvmtiError err;
zgu@9748 120
zgu@9748 121 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
zgu@9748 122 JVMTI_VERSION_1_2);
zgu@9748 123 if (res != JNI_OK || jvmti == NULL) {
zgu@9748 124 printf(" Error: wrong result of a valid call to GetEnv!\n");
zgu@9748 125 return JNI_ERR;
zgu@9748 126 }
zgu@9748 127
zgu@9748 128 printf("Enabling following capabilities: can_generate_all_class_hook_events, "
zgu@9748 129 "can_retransform_classes, can_redefine_classes");
zgu@9748 130 memset(&caps, 0, sizeof(caps));
zgu@9748 131 caps.can_generate_all_class_hook_events = 1;
zgu@9748 132 caps.can_retransform_classes = 1;
zgu@9748 133 caps.can_redefine_classes = 1;
zgu@9748 134 printf("\n");
zgu@9748 135
zgu@9748 136 err = (*jvmti)->AddCapabilities(jvmti, &caps);
zgu@9748 137 if (err != JVMTI_ERROR_NONE) {
zgu@9748 138 printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
zgu@9748 139 return JNI_ERR;
zgu@9748 140 }
zgu@9748 141
zgu@9748 142 size = (jint)sizeof(callbacks);
zgu@9748 143
zgu@9748 144 memset(&callbacks, 0, sizeof(callbacks));
zgu@9748 145 callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
zgu@9748 146
zgu@9748 147 err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
zgu@9748 148 if (err != JVMTI_ERROR_NONE) {
zgu@9748 149 printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
zgu@9748 150 return JNI_ERR;
zgu@9748 151 }
zgu@9748 152
zgu@9748 153 err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
zgu@9748 154 if (err != JVMTI_ERROR_NONE) {
zgu@9748 155 printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
zgu@9748 156 return JNI_ERR;
zgu@9748 157 }
zgu@9748 158
zgu@9748 159 return JNI_OK;
zgu@9748 160 }
zgu@9748 161
zgu@9748 162 #ifdef __cplusplus
zgu@9748 163 }
zgu@9748 164 #endif

mercurial