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 */ 21package proguard.classfile.editor; 22 23import proguard.classfile.*; 24import proguard.classfile.attribute.*; 25import proguard.classfile.attribute.visitor.AttributeVisitor; 26import proguard.classfile.constant.RefConstant; 27import proguard.classfile.constant.visitor.ConstantVisitor; 28import proguard.classfile.instruction.*; 29import proguard.classfile.instruction.visitor.InstructionVisitor; 30import proguard.classfile.util.SimplifiedVisitor; 31import proguard.classfile.visitor.MemberVisitor; 32 33/** 34 * This MemberVisitor fixes all inappropriate bridge access flags of the 35 * program methods that it visits, checking whether the methods to which they 36 * bridge have the same name. Some compilers, like in Eclipse and in later 37 * versions of JDK 1.6, complain if they can't find the method with the same 38 * name. 39 * 40 * @author Eric Lafortune 41 */ 42public class BridgeMethodFixer 43extends SimplifiedVisitor 44implements MemberVisitor, 45 AttributeVisitor, 46 InstructionVisitor, 47 ConstantVisitor 48{ 49 private static final boolean DEBUG = false; 50 51 52 // Return values for the visitor methods. 53 private String bridgedMethodName; 54 55 56 // Implementations for MemberVisitor. 57 58 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 59 { 60 if ((programMethod.getAccessFlags() & ClassConstants.ACC_BRIDGE) != 0) 61 { 62 programMethod.attributesAccept(programClass, this); 63 } 64 } 65 66 67 // Implementations for AttributeVisitor. 68 69 public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 70 71 72 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 73 { 74 // Go over the instructions of the bridge method. 75 codeAttribute.instructionsAccept(clazz, method, this); 76 } 77 78 79 // Implementations for InstructionVisitor. 80 81 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} 82 83 84 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 85 { 86 switch (constantInstruction.opcode) 87 { 88 case InstructionConstants.OP_INVOKEVIRTUAL: 89 case InstructionConstants.OP_INVOKESPECIAL: 90 case InstructionConstants.OP_INVOKESTATIC: 91 case InstructionConstants.OP_INVOKEINTERFACE: 92 // Get the name of the bridged method. 93 clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); 94 95 // Check if the name is different. 96 if (!method.getName(clazz).equals(bridgedMethodName)) 97 { 98 if (DEBUG) 99 { 100 System.out.println("BridgeMethodFixer: ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] does not bridge to ["+bridgedMethodName+"]"); 101 } 102 103 // Clear the bridge flag. 104 ((ProgramMethod)method).u2accessFlags &= ~ClassConstants.ACC_BRIDGE; 105 } 106 break; 107 } 108 } 109 110 111 // Implementations for ConstantVisitor. 112 113 public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant) 114 { 115 bridgedMethodName = refConstant.getName(clazz); 116 } 117}