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, i.e., 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, i.e., 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 * @return deep copy of this object 126 */ 127 public CodeException copy() { 128 try { 129 return (CodeException) clone(); 130 } catch (final CloneNotSupportedException e) { 131 // TODO should this throw? 132 } 133 return null; 134 } 135 136 /** 137 * Dumps code exception to file stream in binary format. 138 * 139 * @param file Output file stream 140 * @throws IOException if an I/O error occurs. 141 */ 142 public void dump(final DataOutputStream file) throws IOException { 143 file.writeShort(startPc); 144 file.writeShort(endPc); 145 file.writeShort(handlerPc); 146 file.writeShort(catchType); 147 } 148 149 /** 150 * @return 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught. 151 */ 152 public int getCatchType() { 153 return catchType; 154 } 155 156 /** 157 * @return Exclusive end index of the region where the handler is active. 158 */ 159 public int getEndPC() { 160 return endPc; 161 } 162 163 /** 164 * @return Starting address of exception handler, relative to the code. 165 */ 166 public int getHandlerPC() { 167 return handlerPc; 168 } 169 170 /** 171 * @return Inclusive start index of the region where the handler is active. 172 */ 173 public int getStartPC() { 174 return startPc; 175 } 176 177 /** 178 * @param catchType the type of exception that is caught 179 */ 180 public void setCatchType(final int catchType) { 181 this.catchType = catchType; 182 } 183 184 /** 185 * @param endPc end of handled block 186 */ 187 public void setEndPC(final int endPc) { 188 this.endPc = endPc; 189 } 190 191 /** 192 * @param handlerPc where the actual code is 193 */ 194 public void setHandlerPC(final int handlerPc) { // TODO unused 195 this.handlerPc = handlerPc; 196 } 197 198 /** 199 * @param startPc start of handled block 200 */ 201 public void setStartPC(final int startPc) { // TODO unused 202 this.startPc = startPc; 203 } 204 205 /** 206 * @return String representation. 207 */ 208 @Override 209 public String toString() { 210 return "CodeException(startPc = " + startPc + ", endPc = " + endPc + ", handlerPc = " + handlerPc + ", catchType = " + catchType + ")"; 211 } 212 213 public String toString(final ConstantPool cp) { 214 return toString(cp, true); 215 } 216 217 /** 218 * @param cp constant pool source. 219 * @param verbose Output more if true. 220 * @return String representation. 221 */ 222 public String toString(final ConstantPool cp, final boolean verbose) { 223 final String str; 224 if (catchType == 0) { 225 str = "<Any exception>(0)"; 226 } else { 227 str = Utility.compactClassName(cp.getConstantString(catchType, Const.CONSTANT_Class), false) + (verbose ? "(" + catchType + ")" : ""); 228 } 229 return startPc + "\t" + endPc + "\t" + handlerPc + "\t" + str; 230 } 231}