001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.classfile; 020 021import java.io.DataInput; 022import java.io.DataOutputStream; 023import java.io.IOException; 024 025import org.apache.bcel.Const; 026import org.apache.bcel.Constants; 027import org.apache.bcel.util.Args; 028 029/** 030 * This class represents an entry in the exception table of the <em>Code</em> attribute and is used only there. It 031 * contains a range in which a particular exception handler is active. 032 * 033 * <pre> 034 * Code_attribute { 035 * u2 attribute_name_index; 036 * u4 attribute_length; 037 * u2 max_stack; 038 * u2 max_locals; 039 * u4 code_length; 040 * u1 code[code_length]; 041 * u2 exception_table_length; 042 * { 043 * u2 start_pc; 044 * u2 end_pc; 045 * u2 handler_pc; 046 * u2 catch_type; 047 * } exception_table[exception_table_length]; 048 * u2 attributes_count; 049 * attribute_info attributes[attributes_count]; 050 * } 051 * </pre> 052 * 053 * @see Code 054 */ 055public final class CodeException implements Cloneable, Node, Constants { 056 057 /** 058 * Empty array. 059 */ 060 static final CodeException[] EMPTY_ARRAY = {}; 061 062 /** Range in the code the exception handler. */ 063 private int startPc; 064 065 /** Active. startPc is inclusive, endPc exclusive. */ 066 private int endPc; 067 068 /** 069 * Starting address of exception handler, that is, an offset from start of code. 070 */ 071 private int handlerPc; 072 073 /* 074 * If this is zero the handler catches any exception, otherwise it points to the exception class which is to be caught. 075 */ 076 private int catchType; 077 078 /** 079 * Constructs a new instance from another instance. 080 * 081 * @param c Source for copying. 082 */ 083 public CodeException(final CodeException c) { 084 this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType()); 085 } 086 087 /** 088 * Constructs a new instance from a DataInput. 089 * 090 * @param file Input stream. 091 * @throws IOException if an I/O error occurs. 092 */ 093 CodeException(final DataInput file) throws IOException { 094 this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort()); 095 } 096 097 /** 098 * Constructs a new instance. 099 * 100 * @param startPc Range in the code the exception handler is active, startPc is inclusive while. 101 * @param endPc is exclusive. 102 * @param handlerPc Starting address of exception handler, that is, an offset from start of code. 103 * @param catchType If zero the handler catches any exception, otherwise it points to the exception class which is to be 104 * caught. 105 */ 106 public CodeException(final int startPc, final int endPc, final int handlerPc, final int catchType) { 107 this.startPc = Args.requireU2(startPc, "startPc"); 108 this.endPc = Args.requireU2(endPc, "endPc"); 109 this.handlerPc = Args.requireU2(handlerPc, "handlerPc"); 110 this.catchType = Args.requireU2(catchType, "catchType"); 111 } 112 113 /** 114 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 115 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 116 * 117 * @param v Visitor object. 118 */ 119 @Override 120 public void accept(final Visitor v) { 121 v.visitCodeException(this); 122 } 123 124 /** 125 * Creates a deep copy of this object. 126 * 127 * @return deep copy of this object. 128 */ 129 public CodeException copy() { 130 try { 131 return (CodeException) clone(); 132 } catch (final CloneNotSupportedException e) { 133 // TODO should this throw? 134 } 135 return null; 136 } 137 138 /** 139 * Dumps code exception to file stream in binary format. 140 * 141 * @param file Output file stream. 142 * @throws IOException if an I/O error occurs. 143 */ 144 public void dump(final DataOutputStream file) throws IOException { 145 file.writeShort(startPc); 146 file.writeShort(endPc); 147 file.writeShort(handlerPc); 148 file.writeShort(catchType); 149 } 150 151 /** 152 * Gets the type of exception that is caught. 153 * 154 * @return 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught. 155 */ 156 public int getCatchType() { 157 return catchType; 158 } 159 160 /** 161 * Gets the exclusive end index of the region where the handler is active. 162 * 163 * @return Exclusive end index of the region where the handler is active. 164 */ 165 public int getEndPC() { 166 return endPc; 167 } 168 169 /** 170 * Gets the starting address of exception handler, relative to the code. 171 * 172 * @return Starting address of exception handler, relative to the code. 173 */ 174 public int getHandlerPC() { 175 return handlerPc; 176 } 177 178 /** 179 * Gets the inclusive start index of the region where the handler is active. 180 * 181 * @return Inclusive start index of the region where the handler is active. 182 */ 183 public int getStartPC() { 184 return startPc; 185 } 186 187 /** 188 * Sets the type of exception that is caught. 189 * 190 * @param catchType the type of exception that is caught. 191 */ 192 public void setCatchType(final int catchType) { 193 this.catchType = catchType; 194 } 195 196 /** 197 * Sets the end of handled block. 198 * 199 * @param endPc end of handled block. 200 */ 201 public void setEndPC(final int endPc) { 202 this.endPc = endPc; 203 } 204 205 /** 206 * Sets where the actual code is. 207 * 208 * @param handlerPc where the actual code is. 209 */ 210 public void setHandlerPC(final int handlerPc) { // TODO unused 211 this.handlerPc = handlerPc; 212 } 213 214 /** 215 * Sets the start of handled block. 216 * 217 * @param startPc start of handled block. 218 */ 219 public void setStartPC(final int startPc) { // TODO unused 220 this.startPc = startPc; 221 } 222 223 /** 224 * Gets a string representation. 225 * 226 * @return String representation. 227 */ 228 @Override 229 public String toString() { 230 return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " + handlerPc + ", catchType = " + catchType + ")"; 231 } 232 233 /** 234 * Gets a string representation with constant pool. 235 * 236 * @param cp constant pool source. 237 * @return String representation. 238 */ 239 public String toString(final ConstantPool cp) { 240 return toString(cp, true); 241 } 242 243 /** 244 * Gets a string representation with constant pool. 245 * 246 * @param cp constant pool source. 247 * @param verbose Output more if true. 248 * @return String representation. 249 */ 250 public String toString(final ConstantPool cp, final boolean verbose) { 251 final String str; 252 if (catchType == 0) { 253 str = "<Any exception>(0)"; 254 } else { 255 str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) + (verbose ? "(" + catchType + ")" : ""); 256 } 257 return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str; 258 } 259}