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