001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.optimize;
022:
023: import proguard.classfile.*;
024: import proguard.classfile.attribute.*;
025: import proguard.classfile.attribute.visitor.AttributeVisitor;
026: import proguard.classfile.constant.*;
027: import proguard.classfile.constant.visitor.ConstantVisitor;
028: import proguard.classfile.editor.CodeAttributeEditor;
029: import proguard.classfile.instruction.*;
030: import proguard.classfile.instruction.visitor.InstructionVisitor;
031: import proguard.classfile.util.SimplifiedVisitor;
032: import proguard.classfile.visitor.MemberVisitor;
033:
034: /**
035: * This AttributeVisitor adds an additional integer parameter to the tweaked
036: * initialization method invocations that it visits.
037: */
038: public class DuplicateInitializerInvocationFixer extends
039: SimplifiedVisitor implements AttributeVisitor,
040: InstructionVisitor, ConstantVisitor, MemberVisitor {
041: private static final boolean DEBUG = false;
042:
043: private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
044:
045: private String descriptor;
046: private boolean hasBeenFixed;
047:
048: // Implementations for AttributeVisitor.
049:
050: public void visitAnyAttribute(Clazz clazz, Attribute attribute) {
051: }
052:
053: public void visitCodeAttribute(Clazz clazz, Method method,
054: CodeAttribute codeAttribute) {
055:
056: // Reset the code changes.
057: codeAttributeEditor.reset(codeAttribute.u4codeLength);
058:
059: // Fix any duplicate constructor invocations.
060: codeAttribute.instructionsAccept(clazz, method, this );
061:
062: // Apply all accumulated changes to the code.
063: codeAttributeEditor.visitCodeAttribute(clazz, method,
064: codeAttribute);
065: }
066:
067: // Implementations for InstructionVisitor.
068:
069: public void visitAnyInstruction(Clazz clazz, Method method,
070: CodeAttribute codeAttribute, int offset,
071: Instruction instruction) {
072: }
073:
074: public void visitConstantInstruction(Clazz clazz, Method method,
075: CodeAttribute codeAttribute, int offset,
076: ConstantInstruction constantInstruction) {
077: if (constantInstruction.opcode == InstructionConstants.OP_INVOKESPECIAL) {
078: hasBeenFixed = false;
079: clazz.constantPoolEntryAccept(
080: constantInstruction.constantIndex, this );
081:
082: if (hasBeenFixed) {
083: Instruction extraInstruction = new SimpleInstruction(
084: InstructionConstants.OP_ICONST_0);
085:
086: codeAttributeEditor.insertBeforeInstruction(offset,
087: extraInstruction);
088:
089: if (DEBUG) {
090: System.out
091: .println("DuplicateInitializerInvocationFixer:");
092: System.out.println(" Inserting "
093: + extraInstruction.toString() + " before "
094: + constantInstruction.toString(offset));
095: }
096: }
097: }
098: }
099:
100: // Implementations for ConstantVisitor.
101:
102: public void visitMethodrefConstant(Clazz clazz,
103: MethodrefConstant methodrefConstant) {
104: // Check the referenced constructor descriptor.
105: descriptor = methodrefConstant.getType(clazz);
106: methodrefConstant.referencedMemberAccept(this );
107: }
108:
109: // Implementations for MemberVisitor.
110:
111: public void visitLibraryMethod(LibraryClass libraryClass,
112: LibraryMethod libraryMethod) {
113: }
114:
115: public void visitProgramMethod(ProgramClass programClass,
116: ProgramMethod programMethod) {
117: hasBeenFixed = !descriptor.equals(programMethod
118: .getDescriptor(programClass));
119: }
120: }
|