ExceptionInstructionChecker.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.optimize.info; 22 23import proguard.classfile.*; 24import proguard.classfile.attribute.CodeAttribute; 25import proguard.classfile.constant.RefConstant; 26import proguard.classfile.constant.visitor.ConstantVisitor; 27import proguard.classfile.instruction.*; 28import proguard.classfile.instruction.visitor.InstructionVisitor; 29import proguard.classfile.util.SimplifiedVisitor; 30import proguard.classfile.visitor.MemberVisitor; 31 32/** 33 * This class can tell whether an instruction might throw exceptions. 34 * 35 * @author Eric Lafortune 36 */ 37public class ExceptionInstructionChecker 38extends SimplifiedVisitor 39implements InstructionVisitor 40// ConstantVisitor, 41// MemberVisitor 42{ 43 // A return value for the visitor methods. 44 private boolean mayThrowExceptions; 45 46 47 /** 48 * Returns whether the given instruction may throw exceptions. 49 */ 50 public boolean mayThrowExceptions(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) 51 { 52 mayThrowExceptions = false; 53 54 instruction.accept(clazz, method, codeAttribute, offset, this); 55 56 return mayThrowExceptions; 57 } 58 59 60 // Implementations for InstructionVisitor. 61 62 public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} 63 64 65 public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 66 { 67 byte opcode = simpleInstruction.opcode; 68 69 // Check for instructions that may throw exceptions. 70 // Note that monitorexit can not sensibly throw exceptions, except the 71 // broken and deprecated asynchronous ThreadDeath. Removing the 72 // artificial infinite looping exception blocks that recent compilers 73 // add does not strictly follow the JVM specs, but it does have the 74 // additional benefit of avoiding a bug in the JVM in JDK 1.1. 75 switch (opcode) 76 { 77 case InstructionConstants.OP_IDIV: 78 case InstructionConstants.OP_LDIV: 79 case InstructionConstants.OP_IREM: 80 case InstructionConstants.OP_LREM: 81 case InstructionConstants.OP_IALOAD: 82 case InstructionConstants.OP_LALOAD: 83 case InstructionConstants.OP_FALOAD: 84 case InstructionConstants.OP_DALOAD: 85 case InstructionConstants.OP_AALOAD: 86 case InstructionConstants.OP_BALOAD: 87 case InstructionConstants.OP_CALOAD: 88 case InstructionConstants.OP_SALOAD: 89 case InstructionConstants.OP_IASTORE: 90 case InstructionConstants.OP_LASTORE: 91 case InstructionConstants.OP_FASTORE: 92 case InstructionConstants.OP_DASTORE: 93 case InstructionConstants.OP_AASTORE: 94 case InstructionConstants.OP_BASTORE: 95 case InstructionConstants.OP_CASTORE: 96 case InstructionConstants.OP_SASTORE: 97 case InstructionConstants.OP_NEWARRAY: 98 case InstructionConstants.OP_ARRAYLENGTH: 99 case InstructionConstants.OP_ATHROW: 100 case InstructionConstants.OP_MONITORENTER: 101 // These instructions may throw exceptions. 102 mayThrowExceptions = true; 103 } 104 105 } 106 107 108 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 109 { 110 byte opcode = constantInstruction.opcode; 111 112 // Check for instructions that may throw exceptions. 113 switch (opcode) 114 { 115 case InstructionConstants.OP_GETSTATIC: 116 case InstructionConstants.OP_PUTSTATIC: 117 case InstructionConstants.OP_GETFIELD: 118 case InstructionConstants.OP_PUTFIELD: 119 case InstructionConstants.OP_INVOKEVIRTUAL: 120 case InstructionConstants.OP_INVOKESPECIAL: 121 case InstructionConstants.OP_INVOKESTATIC: 122 case InstructionConstants.OP_INVOKEINTERFACE: 123 case InstructionConstants.OP_INVOKEDYNAMIC: 124 case InstructionConstants.OP_NEW: 125 case InstructionConstants.OP_ANEWARRAY: 126 case InstructionConstants.OP_CHECKCAST: 127 case InstructionConstants.OP_INSTANCEOF: 128 case InstructionConstants.OP_MULTIANEWARRAY: 129 // These instructions may throw exceptions. 130 mayThrowExceptions = true; 131 } 132 133// case InstructionConstants.OP_INVOKEVIRTUAL: 134// case InstructionConstants.OP_INVOKESPECIAL: 135// case InstructionConstants.OP_INVOKESTATIC: 136// case InstructionConstants.OP_INVOKEINTERFACE: 137// // Check if the invoking the method may throw an exception. 138// clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); 139 } 140 141 142// // Implementations for ConstantVisitor. 143// 144// public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant) 145// { 146// Member referencedMember = refConstant.referencedMember; 147// 148// // Do we have a reference to the method? 149// if (referencedMember == null) 150// { 151// // We'll have to assume invoking the unknown method may throw an 152// // an exception. 153// mayThrowExceptions = true; 154// } 155// else 156// { 157// // First check the referenced method itself. 158// refConstant.referencedMemberAccept(this); 159// 160// // If the result isn't conclusive, check down the hierarchy. 161// if (!mayThrowExceptions) 162// { 163// Clazz referencedClass = refConstant.referencedClass; 164// Method referencedMethod = (Method)referencedMember; 165// 166// // Check all other implementations of the method in the class 167// // hierarchy. 168// referencedClass.methodImplementationsAccept(referencedMethod, 169// false, 170// false, 171// true, 172// true, 173// this); 174// } 175// } 176// } 177// 178// 179// // Implementations for MemberVisitor. 180// 181// public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 182// { 183// mayThrowExceptions = mayThrowExceptions || 184// ExceptionMethodMarker.mayThrowExceptions(programMethod); 185// } 186// 187// 188// public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 189// { 190// mayThrowExceptions = mayThrowExceptions || 191// !NoExceptionMethodMarker.doesntThrowExceptions(libraryMethod); 192// } 193} 194