KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > optimize > peephole > UnreachableExceptionRemover


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 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  */

21 package proguard.optimize.peephole;
22
23 import proguard.classfile.*;
24 import proguard.classfile.attribute.*;
25 import proguard.classfile.attribute.visitor.*;
26 import proguard.classfile.instruction.*;
27 import proguard.classfile.util.SimplifiedVisitor;
28 import proguard.optimize.info.ExceptionInstructionChecker;
29
30 /**
31  * This AttributeVisitor removes exception handlers that are unreachable in the
32  * code attributes that it visits.
33  *
34  * @author Eric Lafortune
35  */

36 public class UnreachableExceptionRemover
37 extends SimplifiedVisitor
38 implements AttributeVisitor,
39              ExceptionInfoVisitor
40 {
41     private ExceptionInfoVisitor extraExceptionInfoVisitor;
42
43
44     private ExceptionInstructionChecker exceptionInstructionChecker = new ExceptionInstructionChecker();
45
46
47     /**
48      * Creates a new UnreachableExceptionRemover.
49      */

50     public UnreachableExceptionRemover()
51     {
52         this(null);
53     }
54
55
56     /**
57      * Creates a new UnreachableExceptionRemover.
58      * @param extraExceptionInfoVisitor an optional extra visitor for all
59      * removed exceptions.
60      */

61     public UnreachableExceptionRemover(ExceptionInfoVisitor extraExceptionInfoVisitor)
62     {
63         this.extraExceptionInfoVisitor = extraExceptionInfoVisitor;
64     }
65
66
67     // Implementations for AttributeVisitor.
68

69     public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
70
71
72     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
73     {
74         // Go over the exception table.
75
codeAttribute.exceptionsAccept(clazz, method, this);
76
77         // Remove exceptions with empty code blocks.
78
codeAttribute.u2exceptionTableLength =
79             removeEmptyExceptions(codeAttribute.exceptionTable,
80                                   codeAttribute.u2exceptionTableLength);
81     }
82
83
84     // Implementations for ExceptionInfoVisitor.
85

86     public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
87     {
88         if (!mayThrowExceptions(clazz,
89                                 method,
90                                 codeAttribute,
91                                 exceptionInfo.u2startPC,
92                                 exceptionInfo.u2endPC))
93         {
94             // Make the code block empty.
95
exceptionInfo.u2endPC = exceptionInfo.u2startPC;
96
97             if (extraExceptionInfoVisitor != null)
98             {
99                 extraExceptionInfoVisitor.visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo);
100             }
101         }
102     }
103
104
105     // Small utility methods.
106

107     /**
108      * Returns whether the specified block of code may throw exceptions.
109      */

110     private boolean mayThrowExceptions(Clazz clazz,
111                                        Method method,
112                                        CodeAttribute codeAttribute,
113                                        int startOffset,
114                                        int endOffset)
115     {
116         byte[] code = codeAttribute.code;
117
118         // Go over all instructions.
119
int offset = startOffset;
120         while (offset < endOffset)
121         {
122             // Get the current instruction.
123
Instruction instruction = InstructionFactory.create(code, offset);
124
125             // Check if it may be throwing exceptions.
126
if (exceptionInstructionChecker.mayThrowExceptions(clazz,
127                                                                method,
128                                                                codeAttribute,
129                                                                offset,
130                                                                instruction))
131             {
132                 return true;
133             }
134
135             // Go to the next instruction.
136
offset += instruction.length(offset);
137         }
138
139         return false;
140     }
141
142
143     /**
144      * Returns the given list of exceptions, without the ones that have empty
145      * code blocks.
146      */

147     private int removeEmptyExceptions(ExceptionInfo[] exceptionInfos,
148                                       int exceptionInfoCount)
149     {
150         // Overwrite all empty exceptions.
151
int newIndex = 0;
152         for (int index = 0; index < exceptionInfoCount; index++)
153         {
154             ExceptionInfo exceptionInfo = exceptionInfos[index];
155             if (exceptionInfo.u2startPC < exceptionInfo.u2endPC)
156             {
157                 exceptionInfos[newIndex++] = exceptionInfo;
158             }
159         }
160
161         return newIndex;
162     }
163 }
164
Popular Tags