DynamicMemberReferenceInitializer.java revision cfead78069f3dc32998dc118ee08cab3867acea2
1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21package proguard.classfile.util; 22 23import proguard.classfile.*; 24import proguard.classfile.attribute.CodeAttribute; 25import proguard.classfile.attribute.visitor.AttributeVisitor; 26import proguard.classfile.constant.*; 27import proguard.classfile.constant.visitor.ConstantVisitor; 28import proguard.classfile.instruction.*; 29import proguard.classfile.instruction.visitor.InstructionVisitor; 30import proguard.classfile.visitor.*; 31import proguard.util.StringMatcher; 32 33/** 34 * This InstructionVisitor initializes any constant 35 * <code>Class.get[Declared]{Field,Method}</code> references of all instructions 36 * it visits. More specifically, it fills out the references of string constant 37 * pool entries that refer to a class member in the program class pool or in the 38 * library class pool. 39 * <p> 40 * It optionally prints notes if on usage of 41 * <code>(SomeClass)Class.forName(variable).newInstance()</code>. 42 * <p> 43 * The class hierarchy and references must be initialized before using this 44 * visitor. 45 * 46 * @see ClassSuperHierarchyInitializer 47 * @see ClassReferenceInitializer 48 * 49 * @author Eric Lafortune 50 */ 51public class DynamicMemberReferenceInitializer 52extends SimplifiedVisitor 53implements InstructionVisitor, 54 ConstantVisitor, 55 AttributeVisitor, 56 MemberVisitor 57{ 58 /* 59 private static boolean DEBUG = true; 60 /*/ 61 private static final boolean DEBUG = false; 62 //*/ 63 64 public static final int CLASS_INDEX = InstructionSequenceMatcher.X; 65 public static final int MEMBER_NAME_INDEX = InstructionSequenceMatcher.Y; 66 public static final int TYPE_CLASS_INDEX = InstructionSequenceMatcher.Z; 67 68 public static final int PARAMETER0_CLASS_INDEX = InstructionSequenceMatcher.A; 69 public static final int PARAMETER1_CLASS_INDEX = InstructionSequenceMatcher.B; 70 public static final int PARAMETER2_CLASS_INDEX = InstructionSequenceMatcher.C; 71 public static final int PARAMETER3_CLASS_INDEX = InstructionSequenceMatcher.D; 72 73 74 private final Constant[] GET_FIELD_CONSTANTS = new Constant[] 75 { 76 new MethodrefConstant(1, 2, null, null), 77 new ClassConstant(3, null), 78 new NameAndTypeConstant(4, 5), 79 new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS), 80 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_CLASS_GET_FIELD), 81 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_FIELD), 82 }; 83 84 private final Constant[] GET_DECLARED_FIELD_CONSTANTS = new Constant[] 85 { 86 new MethodrefConstant(1, 2, null, null), 87 new ClassConstant(3, null), 88 new NameAndTypeConstant(4, 5), 89 new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS), 90 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_FIELD), 91 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD), 92 }; 93 94 private final Constant[] GET_CONSTRUCTOR_CONSTANTS = new Constant[] 95 { 96 new MethodrefConstant(1, 2, null, null), 97 new ClassConstant(3, null), 98 new NameAndTypeConstant(4, 5), 99 new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS), 100 new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR), 101 new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR), 102 }; 103 104 private final Constant[] GET_DECLARED_CONSTRUCTOR_CONSTANTS = new Constant[] 105 { 106 new MethodrefConstant(1, 2, null, null), 107 new ClassConstant(3, null), 108 new NameAndTypeConstant(4, 5), 109 new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS), 110 new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR), 111 new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR), 112 }; 113 114 private final Constant[] GET_METHOD_CONSTANTS = new Constant[] 115 { 116 new MethodrefConstant(1, 2, null, null), 117 new ClassConstant(3, null), 118 new NameAndTypeConstant(4, 5), 119 new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS), 120 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_CLASS_GET_METHOD), 121 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_METHOD), 122 }; 123 124 private final Constant[] GET_DECLARED_METHOD_CONSTANTS = new Constant[] 125 { 126 new MethodrefConstant(1, 2, null, null), 127 new ClassConstant(3, null), 128 new NameAndTypeConstant(4, 5), 129 new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS), 130 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_CLASS_GET_DECLARED_METHOD), 131 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD), 132 }; 133 134 private final Constant[] NEW_INTEGER_UPDATER_CONSTANTS = new Constant[] 135 { 136 new MethodrefConstant(1, 2, null, null), 137 new ClassConstant(3, null), 138 new NameAndTypeConstant(4, 5), 139 new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER), 140 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER), 141 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_INTEGER_UPDATER), 142 }; 143 144 private final Constant[] NEW_LONG_UPDATER_CONSTANTS = new Constant[] 145 { 146 new MethodrefConstant(1, 2, null, null), 147 new ClassConstant(3, null), 148 new NameAndTypeConstant(4, 5), 149 new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER), 150 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER), 151 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_LONG_UPDATER), 152 }; 153 154 private final Constant[] NEW_REFERENCE_UPDATER_CONSTANTS = new Constant[] 155 { 156 new MethodrefConstant(1, 2, null, null), 157 new ClassConstant(3, null), 158 new NameAndTypeConstant(4, 5), 159 new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER), 160 new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER), 161 new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_REFERENCE_UPDATER), 162 }; 163 164 // SomeClass.class.get[Declared]Field("someField"). 165 private final Instruction[] CONSTANT_GET_FIELD_INSTRUCTIONS = new Instruction[] 166 { 167 new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), 168 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 169 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 170 }; 171 172// // SomeClass.class.get[Declared]Constructor(new Class[] {}). 173// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[] 174// { 175// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), 176// new SimpleInstruction(InstructionConstants.OP_ICONST_0), 177// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 178// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 179// }; 180// 181// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class }). 182// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[] 183// { 184// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), 185// new SimpleInstruction(InstructionConstants.OP_ICONST_1), 186// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 187// new SimpleInstruction(InstructionConstants.OP_DUP), 188// new SimpleInstruction(InstructionConstants.OP_ICONST_0), 189// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), 190// new SimpleInstruction(InstructionConstants.OP_AASTORE), 191// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 192// }; 193// 194// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class, B.class }). 195// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[] 196// { 197// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), 198// new SimpleInstruction(InstructionConstants.OP_ICONST_2), 199// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 200// new SimpleInstruction(InstructionConstants.OP_DUP), 201// new SimpleInstruction(InstructionConstants.OP_ICONST_0), 202// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), 203// new SimpleInstruction(InstructionConstants.OP_AASTORE), 204// new SimpleInstruction(InstructionConstants.OP_DUP), 205// new SimpleInstruction(InstructionConstants.OP_ICONST_1), 206// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX), 207// new SimpleInstruction(InstructionConstants.OP_AASTORE), 208// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 209// }; 210 211 // SomeClass.class.get[Declared]Method("someMethod", new Class[] {}). 212 private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS0 = new Instruction[] 213 { 214 new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), 215 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 216 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 217 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 218 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 219 }; 220 221 // SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class }). 222 private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS1 = new Instruction[] 223 { 224 new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), 225 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 226 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 227 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 228 new SimpleInstruction(InstructionConstants.OP_DUP), 229 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 230 new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), 231 new SimpleInstruction(InstructionConstants.OP_AASTORE), 232 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 233 }; 234 235 // SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class, B.class }). 236 private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS2 = new Instruction[] 237 { 238 new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), 239 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 240 new SimpleInstruction(InstructionConstants.OP_ICONST_2), 241 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 242 new SimpleInstruction(InstructionConstants.OP_DUP), 243 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 244 new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), 245 new SimpleInstruction(InstructionConstants.OP_AASTORE), 246 new SimpleInstruction(InstructionConstants.OP_DUP), 247 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 248 new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX), 249 new SimpleInstruction(InstructionConstants.OP_AASTORE), 250 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 251 }; 252 253 // AtomicIntegerFieldUpdater.newUpdater(A.class, "someField"). 254 // AtomicLongFieldUpdater.newUpdater(A.class, "someField"). 255 private final Instruction[] CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS = new Instruction[] 256 { 257 new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), 258 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 259 new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0), 260 }; 261 262 // AtomicReferenceFieldUpdater.newUpdater(A.class, B.class, "someField"). 263 private final Instruction[] CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS = new Instruction[] 264 { 265 new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), 266 new ConstantInstruction(InstructionConstants.OP_LDC, TYPE_CLASS_INDEX), 267 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 268 new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0), 269 }; 270 271 // get[Declared]Field("someField"). 272 private final Instruction[] GET_FIELD_INSTRUCTIONS = new Instruction[] 273 { 274 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 275 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 276 }; 277 278// // get[Declared]Constructor(new Class[] {}). 279// private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[] 280// { 281// new SimpleInstruction(InstructionConstants.OP_ICONST_0), 282// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 283// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 284// }; 285 286 // get[Declared]Constructor(new Class[] { A.class }). 287 private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[] 288 { 289 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 290 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 291 new SimpleInstruction(InstructionConstants.OP_DUP), 292 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 293 new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), 294 new SimpleInstruction(InstructionConstants.OP_AASTORE), 295 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 296 }; 297 298 // get[Declared]Constructor(new Class[] { A.class, B.class }). 299 private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[] 300 { 301 new SimpleInstruction(InstructionConstants.OP_ICONST_2), 302 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 303 new SimpleInstruction(InstructionConstants.OP_DUP), 304 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 305 new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), 306 new SimpleInstruction(InstructionConstants.OP_AASTORE), 307 new SimpleInstruction(InstructionConstants.OP_DUP), 308 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 309 new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX), 310 new SimpleInstruction(InstructionConstants.OP_AASTORE), 311 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 312 }; 313 314 // get[Declared]Method("someMethod", new Class[] {}). 315 private final Instruction[] GET_METHOD_INSTRUCTIONS0 = new Instruction[] 316 { 317 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 318 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 319 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 320 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 321 }; 322 323 // get[Declared]Method("someMethod", new Class[] { A.class }). 324 private final Instruction[] GET_METHOD_INSTRUCTIONS1 = new Instruction[] 325 { 326 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 327 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 328 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 329 new SimpleInstruction(InstructionConstants.OP_DUP), 330 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 331 new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), 332 new SimpleInstruction(InstructionConstants.OP_AASTORE), 333 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 334 }; 335 336 // get[Declared]Method("someMethod", new Class[] { A.class, B.class }). 337 private final Instruction[] GET_METHOD_INSTRUCTIONS2 = new Instruction[] 338 { 339 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 340 new SimpleInstruction(InstructionConstants.OP_ICONST_2), 341 new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), 342 new SimpleInstruction(InstructionConstants.OP_DUP), 343 new SimpleInstruction(InstructionConstants.OP_ICONST_0), 344 new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), 345 new SimpleInstruction(InstructionConstants.OP_AASTORE), 346 new SimpleInstruction(InstructionConstants.OP_DUP), 347 new SimpleInstruction(InstructionConstants.OP_ICONST_1), 348 new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX), 349 new SimpleInstruction(InstructionConstants.OP_AASTORE), 350 new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), 351 }; 352 353 // AtomicIntegerFieldUpdater.newUpdater(..., "someField"). 354 // AtomicLongFieldUpdater.newUpdater(..., "someField"). 355 // AtomicReferenceFieldUpdater.newUpdater(..., "someField"). 356 private final Instruction[] NEW_UPDATER_INSTRUCTIONS = new Instruction[] 357 { 358 new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), 359 new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0), 360 }; 361 362 363 private final ClassPool programClassPool; 364 private final ClassPool libraryClassPool; 365 private final WarningPrinter notePrinter; 366 private final StringMatcher noteFieldExceptionMatcher; 367 private final StringMatcher noteMethodExceptionMatcher; 368 369 370 private final InstructionSequenceMatcher constantGetFieldMatcher = 371 new InstructionSequenceMatcher(GET_FIELD_CONSTANTS, 372 CONSTANT_GET_FIELD_INSTRUCTIONS); 373 374 private final InstructionSequenceMatcher constantGetDeclaredFieldMatcher = 375 new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS, 376 CONSTANT_GET_FIELD_INSTRUCTIONS); 377 378// private final InstructionSequenceMatcher constantGetConstructorMatcher0 = 379// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, 380// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0); 381// 382// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher0 = 383// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, 384// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0); 385// 386// private final InstructionSequenceMatcher constantGetConstructorMatcher1 = 387// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, 388// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1); 389// 390// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher1 = 391// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, 392// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1); 393// 394// private final InstructionSequenceMatcher constantGetConstructorMatcher2 = 395// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, 396// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2); 397// 398// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher2 = 399// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, 400// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2); 401 402 private final InstructionSequenceMatcher constantGetMethodMatcher0 = 403 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 404 CONSTANT_GET_METHOD_INSTRUCTIONS0); 405 406 private final InstructionSequenceMatcher constantGetDeclaredMethodMatcher0 = 407 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 408 CONSTANT_GET_METHOD_INSTRUCTIONS0); 409 410 private final InstructionSequenceMatcher constantGetMethodMatcher1 = 411 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 412 CONSTANT_GET_METHOD_INSTRUCTIONS1); 413 414 private final InstructionSequenceMatcher constantGetDeclaredMethodMatcher1 = 415 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 416 CONSTANT_GET_METHOD_INSTRUCTIONS1); 417 418 private final InstructionSequenceMatcher constantGetMethodMatcher2 = 419 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 420 CONSTANT_GET_METHOD_INSTRUCTIONS2); 421 422 private final InstructionSequenceMatcher constantGetDeclaredMethodMatcher2 = 423 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 424 CONSTANT_GET_METHOD_INSTRUCTIONS2); 425 426 private final InstructionSequenceMatcher constantGetIntegerUpdaterMatcher = 427 new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS, 428 CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS); 429 430 private final InstructionSequenceMatcher constantGetLongUpdaterMatcher = 431 new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS, 432 CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS); 433 434 private final InstructionSequenceMatcher constantGetReferenceUpdaterMatcher = 435 new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS, 436 CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS); 437 438 private final InstructionSequenceMatcher getFieldMatcher = 439 new InstructionSequenceMatcher(GET_FIELD_CONSTANTS, 440 GET_FIELD_INSTRUCTIONS); 441 442 private final InstructionSequenceMatcher getDeclaredFieldMatcher = 443 new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS, 444 GET_FIELD_INSTRUCTIONS); 445 446// private final InstructionSequenceMatcher getConstructorMatcher0 = 447// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, 448// GET_CONSTRUCTOR_INSTRUCTIONS0); 449// 450// private final InstructionSequenceMatcher getDeclaredConstructorMatcher0 = 451// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, 452// GET_CONSTRUCTOR_INSTRUCTIONS0); 453 454 private final InstructionSequenceMatcher getConstructorMatcher1 = 455 new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, 456 GET_CONSTRUCTOR_INSTRUCTIONS1); 457 458 private final InstructionSequenceMatcher getDeclaredConstructorMatcher1 = 459 new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, 460 GET_CONSTRUCTOR_INSTRUCTIONS1); 461 462 private final InstructionSequenceMatcher getConstructorMatcher2 = 463 new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, 464 GET_CONSTRUCTOR_INSTRUCTIONS2); 465 466 private final InstructionSequenceMatcher getDeclaredConstructorMatcher2 = 467 new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, 468 GET_CONSTRUCTOR_INSTRUCTIONS2); 469 470 private final InstructionSequenceMatcher getMethodMatcher0 = 471 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 472 GET_METHOD_INSTRUCTIONS0); 473 474 private final InstructionSequenceMatcher getDeclaredMethodMatcher0 = 475 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 476 GET_METHOD_INSTRUCTIONS0); 477 478 private final InstructionSequenceMatcher getMethodMatcher1 = 479 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 480 GET_METHOD_INSTRUCTIONS1); 481 482 private final InstructionSequenceMatcher getDeclaredMethodMatcher1 = 483 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 484 GET_METHOD_INSTRUCTIONS1); 485 486 private final InstructionSequenceMatcher getMethodMatcher2 = 487 new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, 488 GET_METHOD_INSTRUCTIONS2); 489 490 private final InstructionSequenceMatcher getDeclaredMethodMatcher2 = 491 new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, 492 GET_METHOD_INSTRUCTIONS2); 493 494 private final InstructionSequenceMatcher getIntegerUpdaterMatcher = 495 new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS, 496 NEW_UPDATER_INSTRUCTIONS); 497 498 private final InstructionSequenceMatcher getLongUpdaterMatcher = 499 new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS, 500 NEW_UPDATER_INSTRUCTIONS); 501 502 private final InstructionSequenceMatcher getReferenceUpdaterMatcher = 503 new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS, 504 NEW_UPDATER_INSTRUCTIONS); 505 506 private final MemberFinder memberFinder = new MemberFinder(); 507 508 509 // Fields acting as parameters for the visitors. 510 private Clazz referencedClass; 511 private String descriptor; 512 private boolean isDeclared; 513 private boolean isField; 514 515 516 517 /** 518 * Creates a new DynamicMemberReferenceInitializer. 519 */ 520 public DynamicMemberReferenceInitializer(ClassPool programClassPool, 521 ClassPool libraryClassPool, 522 WarningPrinter notePrinter, 523 StringMatcher noteFieldExceptionMatcher, 524 StringMatcher noteMethodExceptionMatcher) 525 { 526 this.programClassPool = programClassPool; 527 this.libraryClassPool = libraryClassPool; 528 this.notePrinter = notePrinter; 529 this.noteFieldExceptionMatcher = noteFieldExceptionMatcher; 530 this.noteMethodExceptionMatcher = noteMethodExceptionMatcher; 531 } 532 533 534 // Implementations for InstructionVisitor. 535 536 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) 537 { 538 // Try to match the SomeClass.class.getField("someField") construct. 539 matchGetMember(clazz, method, codeAttribute, offset, instruction, 540 constantGetFieldMatcher, 541 getFieldMatcher, true, false, null, null); 542 543 // Try to match the SomeClass.class.getDeclaredField("someField") construct. 544 matchGetMember(clazz, method, codeAttribute, offset, instruction, 545 constantGetDeclaredFieldMatcher, 546 getDeclaredFieldMatcher, true, true, null, null); 547 548// // Try to match the SomeClass.class.getConstructor(new Class[] 549// // {}) construct. 550// matchGetMember(clazz, method, codeAttribute, offset, instruction, 551// cnull, //onstantGetConstructorMatcher0, 552// getConstructorMatcher0, false, false, 553// ClassConstants.INTERNAL_METHOD_NAME_INIT, null); 554// 555// // Try to match the SomeClass.class.getDeclaredConstructor(new Class[] 556// // {}) construct. 557// matchGetMember(clazz, method, codeAttribute, offset, instruction, 558// null, //constantGetDeclaredConstructorMatcher0, 559// getDeclaredConstructorMatcher0, false, true, 560// ClassConstants.INTERNAL_METHOD_NAME_INIT, null); 561 562 // Try to match the SomeClass.class.getConstructor(new Class[] 563 // { A.class }) construct. 564 matchGetMember(clazz, method, codeAttribute, offset, instruction, 565 null, //constantGetConstructorMatcher1, 566 getConstructorMatcher1, false, false, 567 ClassConstants.INTERNAL_METHOD_NAME_INIT, null); 568 569 // Try to match the SomeClass.class.getDeclaredConstructor(new Class[] 570 // { A.class }) construct. 571 matchGetMember(clazz, method, codeAttribute, offset, instruction, 572 null, //constantGetDeclaredConstructorMatcher1, 573 getDeclaredConstructorMatcher1, false, true, 574 ClassConstants.INTERNAL_METHOD_NAME_INIT, null); 575 576 // Try to match the SomeClass.class.getConstructor(new Class[] 577 // { A.class, B.class }) construct. 578 matchGetMember(clazz, method, codeAttribute, offset, instruction, 579 null, //constantGetConstructorMatcher2, 580 getConstructorMatcher2, false, false, 581 ClassConstants.INTERNAL_METHOD_NAME_INIT, null); 582 583 // Try to match the SomeClass.class.getDeclaredConstructor(new Class[] 584 // { A.class, B.class }) construct. 585 matchGetMember(clazz, method, codeAttribute, offset, instruction, 586 null, //constantGetDeclaredConstructorMatcher2, 587 getDeclaredConstructorMatcher2, false, true, 588 ClassConstants.INTERNAL_METHOD_NAME_INIT, null); 589 590 // Try to match the SomeClass.class.getMethod("someMethod", new Class[] 591 // {}) construct. 592 matchGetMember(clazz, method, codeAttribute, offset, instruction, 593 constantGetMethodMatcher0, 594 getMethodMatcher0, false, false, null, null); 595 596 // Try to match the SomeClass.class.getDeclaredMethod("someMethod", 597 // new Class[] {}) construct. 598 matchGetMember(clazz, method, codeAttribute, offset, instruction, 599 constantGetDeclaredMethodMatcher0, 600 getDeclaredMethodMatcher0, false, true, null, null); 601 602 // Try to match the SomeClass.class.getMethod("someMethod", new Class[] 603 // { A.class }) construct. 604 matchGetMember(clazz, method, codeAttribute, offset, instruction, 605 constantGetMethodMatcher1, 606 getMethodMatcher1, false, false, null, null); 607 608 // Try to match the SomeClass.class.getDeclaredMethod("someMethod", 609 // new Class[] { A.class }) construct. 610 matchGetMember(clazz, method, codeAttribute, offset, instruction, 611 constantGetDeclaredMethodMatcher1, 612 getDeclaredMethodMatcher1, false, true, null, null); 613 614 // Try to match the SomeClass.class.getMethod("someMethod", new Class[] 615 // { A.class, B.class }) construct. 616 matchGetMember(clazz, method, codeAttribute, offset, instruction, 617 constantGetMethodMatcher2, 618 getMethodMatcher2, false, false, null, null); 619 620 // Try to match the SomeClass.class.getDeclaredMethod("someMethod", 621 // new Class[] { A.class, B.class }) construct. 622 matchGetMember(clazz, method, codeAttribute, offset, instruction, 623 constantGetDeclaredMethodMatcher2, 624 getDeclaredMethodMatcher2, false, true, null, null); 625 626 // Try to match the AtomicIntegerFieldUpdater.newUpdater( 627 // SomeClass.class, "someField") construct. 628 matchGetMember(clazz, method, codeAttribute, offset, instruction, 629 constantGetIntegerUpdaterMatcher, 630 getIntegerUpdaterMatcher, true, false, null, 631 "" + ClassConstants.INTERNAL_TYPE_INT); 632 633 // Try to match the AtomicLongFieldUpdater.newUpdater( 634 // SomeClass.class, "someField") construct. 635 matchGetMember(clazz, method, codeAttribute, offset, instruction, 636 constantGetLongUpdaterMatcher, 637 getLongUpdaterMatcher, true, false, null, 638 "" + ClassConstants.INTERNAL_TYPE_LONG); 639 640 // Try to match the AtomicReferenceFieldUpdater.newUpdater( 641 // SomeClass.class, SomeClass.class, "someField") construct. 642 matchGetMember(clazz, method, codeAttribute, offset, instruction, 643 constantGetReferenceUpdaterMatcher, 644 getReferenceUpdaterMatcher, true, false, null, null); 645 } 646 647 648 /** 649 * Tries to match the next instruction and fills out the string constant 650 * or prints out a note accordingly. 651 */ 652 private void matchGetMember(Clazz clazz, 653 Method method, 654 CodeAttribute codeAttribute, 655 int offset, 656 Instruction instruction, 657 InstructionSequenceMatcher constantSequenceMatcher, 658 InstructionSequenceMatcher variableSequenceMatcher, 659 boolean isField, 660 boolean isDeclared, 661 String defaultName, 662 String defaultDescriptor) 663 { 664 if (constantSequenceMatcher != null) 665 { 666 // Try to match the next instruction in the constant sequence. 667 instruction.accept(clazz, method, codeAttribute, offset, 668 constantSequenceMatcher); 669 670 // Did we find a match to fill out the string constant? 671 if (constantSequenceMatcher.isMatching()) 672 { 673 initializeStringReference(clazz, 674 constantSequenceMatcher, 675 isField, 676 isDeclared, 677 defaultDescriptor); 678 679 // Don't look for the dynamic construct. 680 variableSequenceMatcher.reset(); 681 } 682 } 683 684 // Try to match the next instruction in the variable sequence. 685 instruction.accept(clazz, method, codeAttribute, offset, 686 variableSequenceMatcher); 687 688 // Did we find a match to print out a note? 689 if (variableSequenceMatcher.isMatching()) 690 { 691 // Print out a note about the dynamic invocation. 692 printDynamicInvocationNote(clazz, 693 variableSequenceMatcher, 694 isField, 695 isDeclared, 696 defaultName, 697 defaultDescriptor); 698 } 699 } 700 701 702 /** 703 * Initializes the reference of the matched string constant to the 704 * referenced class member and its class. 705 */ 706 private void initializeStringReference(Clazz clazz, 707 InstructionSequenceMatcher constantSequenceMatcher, 708 boolean isField, 709 boolean isDeclared, 710 String defaultDescriptor) 711 { 712 this.isField = isField; 713 this.isDeclared = isDeclared; 714 715 // Get the member's class. 716 int classIndex = constantSequenceMatcher.matchedConstantIndex(CLASS_INDEX); 717 clazz.constantPoolEntryAccept(classIndex, this); 718 719 // Get the field's reference type, if applicable. 720 int typeClassIndex = constantSequenceMatcher.matchedConstantIndex(TYPE_CLASS_INDEX); 721 descriptor = typeClassIndex <= 0 ? defaultDescriptor : 722 ClassUtil.internalTypeFromClassName(clazz.getClassName(typeClassIndex)); 723 724 // Fill out the matched string constant. 725 int memberNameIndex = constantSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX); 726 clazz.constantPoolEntryAccept(memberNameIndex, this); 727 } 728 729 730 // Implementations for ConstantVisitor. 731 732 /** 733 * Remembers the referenced class. 734 */ 735 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 736 { 737 if (DEBUG) 738 { 739 System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched class ["+classConstant.getName(clazz)+"]"); 740 } 741 742 // Remember the referenced class. 743 referencedClass = ClassUtil.isInternalArrayType(classConstant.getName(clazz)) ? 744 null : 745 classConstant.referencedClass; 746 } 747 748 749 /** 750 * Fills out the link to the referenced class member. 751 */ 752 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 753 { 754 if (referencedClass != null) 755 { 756 String name = stringConstant.getString(clazz); 757 758 if (DEBUG) 759 { 760 System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched string ["+name+"]"); 761 } 762 763 // See if we can find the referenced class member locally, or 764 // somewhere in the hierarchy. 765 Member referencedMember = isDeclared ? isField ? 766 (Member)referencedClass.findField(name, descriptor) : 767 (Member)referencedClass.findMethod(name, descriptor) : 768 (Member)memberFinder.findMember(clazz, 769 referencedClass, 770 name, 771 descriptor, 772 isField); 773 if (referencedMember != null) 774 { 775 stringConstant.referencedMember = referencedMember; 776 stringConstant.referencedClass = isDeclared ? 777 referencedClass : 778 memberFinder.correspondingClass(); 779 } 780 } 781 } 782 783 784 // Small utility methods. 785 786 /** 787 * Prints out a note on the matched dynamic invocation, if necessary. 788 */ 789 private void printDynamicInvocationNote(Clazz clazz, 790 InstructionSequenceMatcher noteSequenceMatcher, 791 boolean isField, 792 boolean isDeclared, 793 String defaultName, 794 String defaultDescriptor) 795 { 796 // Print out a note about the dynamic invocation. 797 if (notePrinter != null && 798 notePrinter.accepts(clazz.getName())) 799 { 800 // Is the class member name in the list of exceptions? 801 StringMatcher noteExceptionMatcher = isField ? 802 noteFieldExceptionMatcher : 803 noteMethodExceptionMatcher; 804 805 int memberNameIndex = noteSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX); 806 String memberName = memberNameIndex <= 0 ? defaultName : 807 clazz.getStringString(memberNameIndex); 808 809 if (noteExceptionMatcher == null || 810 !noteExceptionMatcher.matches(memberName)) 811 { 812 // Compose the external member name and partial descriptor. 813 String externalMemberDescription = memberName; 814 815 if (!isField) 816 { 817 externalMemberDescription += '('; 818 for (int count = 0; count < 2; count++) 819 { 820 int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex( 821 PARAMETER0_CLASS_INDEX + count); 822 if (memberArgumentIndex > 0) 823 { 824 if (count > 0) 825 { 826 externalMemberDescription += ','; 827 } 828 String className = clazz.getClassName(memberArgumentIndex); 829 externalMemberDescription += ClassUtil.isInternalArrayType(className) ? 830 ClassUtil.externalType(className) : 831 ClassUtil.externalClassName(className); 832 } 833 } 834 externalMemberDescription += ')'; 835 } 836 837 // Print out the actual note. 838 notePrinter.print(clazz.getName(), 839 "Note: " + 840 ClassUtil.externalClassName(clazz.getName()) + 841 " accesses a " + 842 (isDeclared ? "declared " : "") + 843 (isField ? "field" : 844 memberName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? 845 "constructor" : "method") + 846 " '" + 847 externalMemberDescription + 848 "' dynamically"); 849 850 // Print out notes about potential candidates. 851 ClassVisitor classVisitor; 852 853 if (isField) 854 { 855 classVisitor = defaultDescriptor == null ? 856 new AllFieldVisitor( 857 new MemberNameFilter(memberName, this)) : 858 new AllFieldVisitor( 859 new MemberNameFilter(memberName, 860 new MemberDescriptorFilter(defaultDescriptor, this))); 861 } 862 else 863 { 864 // Compose the partial method descriptor. 865 String methodDescriptor = "("; 866 for (int count = 0; count < 2; count++) 867 { 868 int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(PARAMETER0_CLASS_INDEX + count); 869 if (memberArgumentIndex > 0) 870 { 871 String className = clazz.getClassName(memberArgumentIndex); 872 methodDescriptor += ClassUtil.isInternalArrayType(className) ? 873 className : 874 ClassUtil.internalTypeFromClassName(className); 875 } 876 } 877 methodDescriptor += ")L***;"; 878 879 classVisitor = 880 new AllMethodVisitor( 881 new MemberNameFilter(memberName, 882 new MemberDescriptorFilter(methodDescriptor, this))); 883 } 884 885 programClassPool.classesAcceptAlphabetically(classVisitor); 886 libraryClassPool.classesAcceptAlphabetically(classVisitor); 887 } 888 } 889 } 890 891 892 // Implementations for MemberVisitor. 893 894 public void visitProgramField(ProgramClass programClass, ProgramField programField) 895 { 896 if (notePrinter.accepts(programClass.getName())) 897 { 898 System.out.println(" Maybe this is program field '" + 899 ClassUtil.externalFullClassDescription(0, programClass.getName()) + 900 " { " + 901 ClassUtil.externalFullFieldDescription(0, programField.getName(programClass), programField.getDescriptor(programClass)) + 902 "; }'"); 903 } 904 } 905 906 907 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 908 { 909 if (notePrinter.accepts(programClass.getName())) 910 { 911 System.out.println(" Maybe this is program method '" + 912 ClassUtil.externalFullClassDescription(0, programClass.getName()) + 913 " { " + 914 ClassUtil.externalFullMethodDescription(programClass.getName(), 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) + 915 "; }'"); 916 } 917 } 918 919 920 public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) 921 { 922 if (notePrinter.accepts(libraryClass.getName())) 923 { 924 System.out.println(" Maybe this is library field '" + 925 ClassUtil.externalFullClassDescription(0, libraryClass.getName()) + 926 " { " + 927 ClassUtil.externalFullFieldDescription(0, libraryField.getName(libraryClass), libraryField.getDescriptor(libraryClass)) + 928 "; }'"); 929 } 930 } 931 932 933 public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 934 { 935 if (notePrinter.accepts(libraryClass.getName())) 936 { 937 System.out.println(" Maybe this is library method '" + 938 ClassUtil.externalFullClassDescription(0, libraryClass.getName()) + 939 " { " + 940 ClassUtil.externalFullMethodDescription(libraryClass.getName(), 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) + 941 "; }'"); 942 } 943 } 944}