1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 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 if (opcode == InstructionConstants.OP_IDIV || 71 opcode == InstructionConstants.OP_LDIV || 72 opcode == InstructionConstants.OP_IREM || 73 opcode == InstructionConstants.OP_LREM || 74 opcode == InstructionConstants.OP_IALOAD || 75 opcode == InstructionConstants.OP_LALOAD || 76 opcode == InstructionConstants.OP_FALOAD || 77 opcode == InstructionConstants.OP_DALOAD || 78 opcode == InstructionConstants.OP_AALOAD || 79 opcode == InstructionConstants.OP_BALOAD || 80 opcode == InstructionConstants.OP_CALOAD || 81 opcode == InstructionConstants.OP_SALOAD || 82 opcode == InstructionConstants.OP_IASTORE || 83 opcode == InstructionConstants.OP_LASTORE || 84 opcode == InstructionConstants.OP_FASTORE || 85 opcode == InstructionConstants.OP_DASTORE || 86 opcode == InstructionConstants.OP_AASTORE || 87 opcode == InstructionConstants.OP_BASTORE || 88 opcode == InstructionConstants.OP_CASTORE || 89 opcode == InstructionConstants.OP_SASTORE || 90 opcode == InstructionConstants.OP_NEWARRAY || 91 opcode == InstructionConstants.OP_ARRAYLENGTH || 92 opcode == InstructionConstants.OP_ATHROW || 93 opcode == InstructionConstants.OP_MONITORENTER || 94 opcode == InstructionConstants.OP_MONITOREXIT) 95 { 96 // These instructions may throw exceptions. 97 mayThrowExceptions = true; 98 } 99 100 } 101 102 103 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 104 { 105 byte opcode = constantInstruction.opcode; 106 107 // Check for instructions that may throw exceptions. 108 if (opcode == InstructionConstants.OP_GETSTATIC || 109 opcode == InstructionConstants.OP_PUTSTATIC || 110 opcode == InstructionConstants.OP_GETFIELD || 111 opcode == InstructionConstants.OP_PUTFIELD || 112 opcode == InstructionConstants.OP_INVOKEVIRTUAL || 113 opcode == InstructionConstants.OP_INVOKESPECIAL || 114 opcode == InstructionConstants.OP_INVOKESTATIC || 115 opcode == InstructionConstants.OP_INVOKEINTERFACE || 116 opcode == InstructionConstants.OP_NEW || 117 opcode == InstructionConstants.OP_ANEWARRAY || 118 opcode == InstructionConstants.OP_CHECKCAST || 119 opcode == InstructionConstants.OP_MULTIANEWARRAY) 120 { 121 // These instructions may throw exceptions. 122 mayThrowExceptions = true; 123 } 124// else 125// if (opcode == InstructionConstants.OP_INVOKEVIRTUAL || 126// opcode == InstructionConstants.OP_INVOKESPECIAL || 127// opcode == InstructionConstants.OP_INVOKESTATIC || 128// opcode == InstructionConstants.OP_INVOKEINTERFACE) 129// { 130// // Check if the invoking the method may throw an exception. 131// clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); 132// } 133 } 134 135 136// // Implementations for ConstantVisitor. 137// 138// public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant) 139// { 140// Member referencedMember = refConstant.referencedMember; 141// 142// // Do we have a reference to the method? 143// if (referencedMember == null) 144// { 145// // We'll have to assume invoking the unknown method may throw an 146// // an exception. 147// mayThrowExceptions = true; 148// } 149// else 150// { 151// // First check the referenced method itself. 152// refConstant.referencedMemberAccept(this); 153// 154// // If the result isn't conclusive, check down the hierarchy. 155// if (!mayThrowExceptions) 156// { 157// Clazz referencedClass = refConstant.referencedClass; 158// Method referencedMethod = (Method)referencedMember; 159// 160// // Check all other implementations of the method in the class 161// // hierarchy. 162// referencedClass.methodImplementationsAccept(referencedMethod, 163// false, 164// false, 165// true, 166// true, 167// this); 168// } 169// } 170// } 171// 172// 173// // Implementations for MemberVisitor. 174// 175// public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 176// { 177// mayThrowExceptions = mayThrowExceptions || 178// ExceptionMethodMarker.mayThrowExceptions(programMethod); 179// } 180// 181// 182// public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 183// { 184// mayThrowExceptions = mayThrowExceptions || 185// !NoExceptionMethodMarker.doesntThrowExceptions(libraryMethod); 186// } 187} 188