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 #define JVM_ACC_SYNTHETIC 0x1000 49 50 static jvmtiEnv *jvmti = NULL; 51 static jvmtiCapabilities caps; 52 static jint result = PASSED; 53 static jboolean printdump = JNI_FALSE; 54 55 #ifdef STATIC_BUILD 56 JNIEXPORT jint JNICALL Agent_OnLoad_issynth001(JavaVM *jvm, char *options, void *reserved) { 57 return Agent_Initialize(jvm, options, reserved); 58 } 59 JNIEXPORT jint JNICALL Agent_OnAttach_issynth001(JavaVM *jvm, char *options, void *reserved) { 60 return Agent_Initialize(jvm, options, reserved); 61 } 62 JNIEXPORT jint JNI_OnLoad_issynth001(JavaVM *jvm, char *options, void *reserved) { 63 return JNI_VERSION_1_8; 64 } 65 #endif 66 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 67 jint res; 68 jvmtiError err; 69 70 if (options != NULL && strcmp(options, "printdump") == 0) { 71 printdump = JNI_TRUE; 72 } 73 74 res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), 75 JVMTI_VERSION_1_1); 76 if (res != JNI_OK || jvmti == NULL) { 77 printf("Wrong result of a valid call to GetEnv!\n"); 78 return JNI_ERR; 79 } 80 81 err = jvmti->GetPotentialCapabilities(&caps); 82 if (err != JVMTI_ERROR_NONE) { 83 printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n", 84 TranslateError(err), err); 85 return JNI_ERR; 86 } 87 88 err = jvmti->AddCapabilities(&caps); 89 if (err != JVMTI_ERROR_NONE) { 90 printf("(AddCapabilities) unexpected error: %s (%d)\n", 91 TranslateError(err), err); 92 return JNI_ERR; 93 } 94 95 err = jvmti->GetCapabilities(&caps); 96 if (err != JVMTI_ERROR_NONE) { 97 printf("(GetCapabilities) unexpected error: %s (%d)\n", 98 TranslateError(err), err); 99 return JNI_ERR; 100 } 101 102 if (!caps.can_get_synthetic_attribute) { 103 printf("Warning: IsMethodSynthetic is not implemented\n"); 104 } 105 106 return JNI_OK; 107 } 108 109 char const *jbooleanToString(jboolean flag) { 110 return ((flag == JNI_TRUE) ? "true" : "false"); 111 } 112 113 JNIEXPORT jint JNICALL 114 checkClassMethods(jclass klass) { 115 jvmtiError err; 116 jmethodID mid; 117 jboolean isSynthetic; 118 jint meth_cnt = 0; 119 jmethodID* methods_ptr = NULL; 120 char* name_ptr = NULL; 121 char* sign_ptr = NULL; 122 int i; 123 124 err = jvmti->GetClassMethods(klass, &meth_cnt, &methods_ptr); 125 if (err != JVMTI_ERROR_NONE) { 126 printf("GetClassMethods unexpected error: %s (%d)\n", 127 TranslateError(err), err); 128 return STATUS_FAILED; 129 } 130 131 for (i = 0; i < meth_cnt; i++) { 132 jint mods; 133 mid = methods_ptr[i]; 134 err = jvmti->GetMethodName(mid, &name_ptr, 135 &sign_ptr, (char **) NULL); 136 if (err != JVMTI_ERROR_NONE) { 137 printf("(GetMethodName#%d) unexpected error: %s (%d)\n", 138 i, TranslateError(err), err); 139 return STATUS_FAILED; 140 } 141 142 printf("Method # %d; name: %s, signature: %s\n", i, name_ptr, sign_ptr); 143 err = jvmti->IsMethodSynthetic(mid, &isSynthetic); 144 if (err != JVMTI_ERROR_NONE) { 145 printf("(IsMethodSynthetic#%d) unexpected error: %s (%d)\n", 146 i, TranslateError(err), err); 147 result = STATUS_FAILED; 148 continue; 149 } 150 151 err = jvmti->GetMethodModifiers(mid, &mods); 152 if (err != JVMTI_ERROR_NONE) { 153 printf("(GetMethodModifiers#%d) unexpected error: %s (%d)\n", 154 i, TranslateError(err), err); 155 result = STATUS_FAILED; 156 continue; 157 } 158 printf("\tACC_SYNTHETIC bit: %d\n", ((mods & JVM_ACC_SYNTHETIC) != 0)); 159 if ((mods & JVM_ACC_SYNTHETIC) && isSynthetic) { 160 printf("\tIsMethodSynthetic result and ACC_SYNTHETIC bit are matched\n"); 161 } else if ((mods & JVM_ACC_SYNTHETIC) || isSynthetic) { 162 printf("Failure: IsMethodSynthetic result and ACC_SYNTHETIC bit don't match\n"); 163 result = STATUS_FAILED; 164 continue; 165 } 166 } 167 printf("\n"); 168 return result; 169 } 170 171 JNIEXPORT jint JNICALL 172 checkClassFields(jclass klass) { 173 jvmtiError err; 174 jfieldID fid; 175 jboolean isSynthetic; 176 jint fld_cnt = 0; 177 jfieldID* fields_ptr = NULL; 178 char* name_ptr = NULL; 179 char* sign_ptr = NULL; 180 int i; 181 182 if (jvmti == NULL) { 183 printf("JVMTI client was not properly loaded!\n"); 184 return STATUS_FAILED; 185 } 186 187 err = jvmti->GetClassFields(klass, &fld_cnt, &fields_ptr); 188 if (err != JVMTI_ERROR_NONE) { 189 printf("GetClassFields unexpected error: %s (%d)\n", 190 TranslateError(err), err); 191 return STATUS_FAILED; 192 } 193 194 for (i = 0; i < fld_cnt; i++) { 195 jint mods; 196 fid = fields_ptr[i]; 197 err = jvmti->GetFieldName(klass, fid, &name_ptr, 198 &sign_ptr, (char **) NULL); 199 if (err != JVMTI_ERROR_NONE) { 200 printf("(GetFieldName#%d) unexpected error: %s (%d)\n", 201 i, TranslateError(err), err); 202 return STATUS_FAILED; 203 } 204 205 printf("Field # %d; name: %s, signature: %s\n", i, name_ptr, sign_ptr); 206 err = jvmti->IsFieldSynthetic(klass, fid, &isSynthetic); 207 if (err != JVMTI_ERROR_NONE) { 208 printf("(IsFieldSynthetic#%d) unexpected error: %s (%d)\n", 209 i, TranslateError(err), err); 210 result = STATUS_FAILED; 211 continue; 212 } 213 214 err = jvmti->GetFieldModifiers(klass, fid, &mods); 215 if (err != JVMTI_ERROR_NONE) { 216 printf("(GetFieldModifiers#%d) unexpected error: %s (%d)\n", 217 i, TranslateError(err), err); 218 result = STATUS_FAILED; 219 continue; 220 } 221 printf("\tACC_SYNTHETIC bit: %d\n", ((mods & JVM_ACC_SYNTHETIC) != 0)); 222 if ((mods & JVM_ACC_SYNTHETIC) && isSynthetic) { 223 printf("\tIsFieldSynthetic result and ACC_SYNTHETIC bit are matched\n"); 224 } else if ((mods & JVM_ACC_SYNTHETIC) || isSynthetic) { 225 printf("Failure: IsFieldSynthetic result and ACC_SYNTHETIC bit don't match\n"); 226 result = STATUS_FAILED; 227 continue; 228 } 229 } 230 231 return result; 232 } 233 234 JNIEXPORT jint JNICALL 235 Java_nsk_jvmti_unit_IsSynthetic_issynth001_check(JNIEnv *env, 236 jclass cls, jclass klass) { 237 238 jvmtiError err; 239 char* class_sign = NULL; 240 241 if (!caps.can_get_synthetic_attribute) { 242 return result; 243 } 244 245 err = jvmti->GetClassSignature(cls, &class_sign, (char **) NULL); 246 if (err != JVMTI_ERROR_NONE) { 247 printf("GetSourceFileName unexpected error: %s (%d)\n", 248 TranslateError(err), err); 249 result = STATUS_FAILED; 250 return result; 251 } else { 252 printf("Class signature: %s\n", class_sign); 253 } 254 255 /* 256 * The following synthetic methods are expected: 257 * Name: class$, Signature: (Ljava/lang/String;)Ljava/lang/Class; 258 * Name: access$000, Signature: (Lnsk/jvmti/unit/IsMethodSynthetic/issynth001;)I 259 */ 260 261 result = checkClassMethods(cls); 262 if (result != PASSED) { 263 return result; 264 } 265 266 err = jvmti->GetClassSignature(klass, &class_sign, (char **) NULL); 267 if (err != JVMTI_ERROR_NONE) { 268 printf("GetSourceFileName unexpected error: %s (%d)\n", 269 TranslateError(err), err); 270 result = STATUS_FAILED; 271 return result; 272 } else { 273 printf("Class signature: %s\n", class_sign); 274 } 275 276 /* Just a sanity check of methods of Inner class. 277 * No synthetic methods are expected here. 278 */ 279 result = checkClassMethods(klass); 280 if (result != PASSED) { 281 return result; 282 } 283 284 /* Check of fields of Inner class. 285 * Just one synthetic field is expected here: 286 * Name: this$0, Signature: Lnsk/jvmti/unit/IsSynthetic/issynth001; 287 */ 288 result = checkClassFields(klass); 289 290 return result; 291 } 292 293 JNIEXPORT jint JNICALL Java_issynth001_getRes(JNIEnv *env, jclass cls) { 294 return result; 295 } 296 297 #ifdef __cplusplus 298 } 299 #endif