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