001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.optimize;
022:
023: import proguard.classfile.*;
024: import proguard.classfile.attribute.*;
025: import proguard.classfile.attribute.annotation.*;
026: import proguard.classfile.attribute.preverification.*;
027: import proguard.classfile.attribute.visitor.AttributeVisitor;
028: import proguard.classfile.util.ClassUtil;
029:
030: /**
031: * This AttributeVisitor delegates its call to another AttributeVisitor, and
032: * prints out the code if the other visitor has changed it.
033: *
034: * @author Eric Lafortune
035: */
036: public class ChangedCodePrinter implements AttributeVisitor {
037: private final AttributeVisitor attributeVisitor;
038:
039: public ChangedCodePrinter(AttributeVisitor attributeVisitor) {
040: this .attributeVisitor = attributeVisitor;
041: }
042:
043: // Implementations for AttributeVisitor.
044:
045: public void visitUnknownAttribute(Clazz clazz,
046: UnknownAttribute unknownAttribute) {
047: attributeVisitor.visitUnknownAttribute(clazz, unknownAttribute);
048: }
049:
050: public void visitSourceFileAttribute(Clazz clazz,
051: SourceFileAttribute sourceFileAttribute) {
052: attributeVisitor.visitSourceFileAttribute(clazz,
053: sourceFileAttribute);
054: }
055:
056: public void visitSourceDirAttribute(Clazz clazz,
057: SourceDirAttribute sourceDirAttribute) {
058: attributeVisitor.visitSourceDirAttribute(clazz,
059: sourceDirAttribute);
060: }
061:
062: public void visitInnerClassesAttribute(Clazz clazz,
063: InnerClassesAttribute innerClassesAttribute) {
064: attributeVisitor.visitInnerClassesAttribute(clazz,
065: innerClassesAttribute);
066: }
067:
068: public void visitEnclosingMethodAttribute(Clazz clazz,
069: EnclosingMethodAttribute enclosingMethodAttribute) {
070: attributeVisitor.visitEnclosingMethodAttribute(clazz,
071: enclosingMethodAttribute);
072: }
073:
074: public void visitDeprecatedAttribute(Clazz clazz,
075: DeprecatedAttribute deprecatedAttribute) {
076: attributeVisitor.visitDeprecatedAttribute(clazz,
077: deprecatedAttribute);
078: }
079:
080: public void visitSyntheticAttribute(Clazz clazz,
081: SyntheticAttribute syntheticAttribute) {
082: attributeVisitor.visitSyntheticAttribute(clazz,
083: syntheticAttribute);
084: }
085:
086: public void visitSignatureAttribute(Clazz clazz,
087: SignatureAttribute syntheticAttribute) {
088: attributeVisitor.visitSignatureAttribute(clazz,
089: syntheticAttribute);
090: }
091:
092: public void visitDeprecatedAttribute(Clazz clazz, Field field,
093: DeprecatedAttribute deprecatedAttribute) {
094: attributeVisitor.visitDeprecatedAttribute(clazz, field,
095: deprecatedAttribute);
096: }
097:
098: public void visitSyntheticAttribute(Clazz clazz, Field field,
099: SyntheticAttribute syntheticAttribute) {
100: attributeVisitor.visitSyntheticAttribute(clazz, field,
101: syntheticAttribute);
102: }
103:
104: public void visitSignatureAttribute(Clazz clazz, Field field,
105: SignatureAttribute syntheticAttribute) {
106: attributeVisitor.visitSignatureAttribute(clazz, field,
107: syntheticAttribute);
108: }
109:
110: public void visitDeprecatedAttribute(Clazz clazz, Method method,
111: DeprecatedAttribute deprecatedAttribute) {
112: attributeVisitor.visitDeprecatedAttribute(clazz, method,
113: deprecatedAttribute);
114: }
115:
116: public void visitSyntheticAttribute(Clazz clazz, Method method,
117: SyntheticAttribute syntheticAttribute) {
118: attributeVisitor.visitSyntheticAttribute(clazz, method,
119: syntheticAttribute);
120: }
121:
122: public void visitSignatureAttribute(Clazz clazz, Method method,
123: SignatureAttribute syntheticAttribute) {
124: attributeVisitor.visitSignatureAttribute(clazz, method,
125: syntheticAttribute);
126: }
127:
128: public void visitConstantValueAttribute(Clazz clazz, Field field,
129: ConstantValueAttribute constantValueAttribute) {
130: attributeVisitor.visitConstantValueAttribute(clazz, field,
131: constantValueAttribute);
132: }
133:
134: public void visitExceptionsAttribute(Clazz clazz, Method method,
135: ExceptionsAttribute exceptionsAttribute) {
136: attributeVisitor.visitExceptionsAttribute(clazz, method,
137: exceptionsAttribute);
138: }
139:
140: public void visitStackMapAttribute(Clazz clazz, Method method,
141: CodeAttribute codeAttribute,
142: StackMapAttribute stackMapAttribute) {
143: attributeVisitor.visitStackMapAttribute(clazz, method,
144: codeAttribute, stackMapAttribute);
145: }
146:
147: public void visitStackMapTableAttribute(Clazz clazz, Method method,
148: CodeAttribute codeAttribute,
149: StackMapTableAttribute stackMapTableAttribute) {
150: attributeVisitor.visitStackMapTableAttribute(clazz, method,
151: codeAttribute, stackMapTableAttribute);
152: }
153:
154: public void visitLineNumberTableAttribute(Clazz clazz,
155: Method method, CodeAttribute codeAttribute,
156: LineNumberTableAttribute lineNumberTableAttribute) {
157: attributeVisitor.visitLineNumberTableAttribute(clazz, method,
158: codeAttribute, lineNumberTableAttribute);
159: }
160:
161: public void visitLocalVariableTableAttribute(Clazz clazz,
162: Method method, CodeAttribute codeAttribute,
163: LocalVariableTableAttribute localVariableTableAttribute) {
164: attributeVisitor.visitLocalVariableTableAttribute(clazz,
165: method, codeAttribute, localVariableTableAttribute);
166: }
167:
168: public void visitLocalVariableTypeTableAttribute(
169: Clazz clazz,
170: Method method,
171: CodeAttribute codeAttribute,
172: LocalVariableTypeTableAttribute localVariableTypeTableAttribute) {
173: attributeVisitor.visitLocalVariableTypeTableAttribute(clazz,
174: method, codeAttribute, localVariableTypeTableAttribute);
175: }
176:
177: public void visitRuntimeVisibleAnnotationsAttribute(
178: Clazz clazz,
179: RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute) {
180: attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz,
181: runtimeVisibleAnnotationsAttribute);
182: }
183:
184: public void visitRuntimeInvisibleAnnotationsAttribute(
185: Clazz clazz,
186: RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute) {
187: attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(
188: clazz, runtimeInvisibleAnnotationsAttribute);
189: }
190:
191: public void visitRuntimeVisibleAnnotationsAttribute(
192: Clazz clazz,
193: Field field,
194: RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute) {
195: attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz,
196: field, runtimeVisibleAnnotationsAttribute);
197: }
198:
199: public void visitRuntimeInvisibleAnnotationsAttribute(
200: Clazz clazz,
201: Field field,
202: RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute) {
203: attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(
204: clazz, field, runtimeInvisibleAnnotationsAttribute);
205: }
206:
207: public void visitRuntimeVisibleAnnotationsAttribute(
208: Clazz clazz,
209: Method method,
210: RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute) {
211: attributeVisitor.visitRuntimeVisibleAnnotationsAttribute(clazz,
212: method, runtimeVisibleAnnotationsAttribute);
213: }
214:
215: public void visitRuntimeInvisibleAnnotationsAttribute(
216: Clazz clazz,
217: Method method,
218: RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute) {
219: attributeVisitor.visitRuntimeInvisibleAnnotationsAttribute(
220: clazz, method, runtimeInvisibleAnnotationsAttribute);
221: }
222:
223: public void visitRuntimeVisibleParameterAnnotationsAttribute(
224: Clazz clazz,
225: Method method,
226: RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute) {
227: attributeVisitor
228: .visitRuntimeVisibleParameterAnnotationsAttribute(
229: clazz, method,
230: runtimeVisibleParameterAnnotationsAttribute);
231: }
232:
233: public void visitRuntimeInvisibleParameterAnnotationsAttribute(
234: Clazz clazz,
235: Method method,
236: RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute) {
237: attributeVisitor
238: .visitRuntimeInvisibleParameterAnnotationsAttribute(
239: clazz, method,
240: runtimeInvisibleParameterAnnotationsAttribute);
241: }
242:
243: public void visitAnnotationDefaultAttribute(Clazz clazz,
244: Method method,
245: AnnotationDefaultAttribute annotationDefaultAttribute) {
246: attributeVisitor.visitAnnotationDefaultAttribute(clazz, method,
247: annotationDefaultAttribute);
248: }
249:
250: public void visitCodeAttribute(Clazz clazz, Method method,
251: CodeAttribute codeAttribute) {
252: byte[] code = codeAttribute.code;
253: byte[] oldCode = new byte[code.length];
254:
255: // Copy the current code.
256: System.arraycopy(code, 0, oldCode, 0,
257: codeAttribute.u4codeLength);
258:
259: // Delegate to the real visitor.
260: attributeVisitor.visitCodeAttribute(clazz, method,
261: codeAttribute);
262:
263: // Check if the code has changed.
264: if (codeHasChanged(codeAttribute, oldCode)) {
265: printChangedCode(clazz, method, codeAttribute, oldCode);
266: }
267: }
268:
269: // Small utility methods.
270:
271: private boolean codeHasChanged(CodeAttribute codeAttribute,
272: byte[] oldCode) {
273: if (oldCode.length != codeAttribute.u4codeLength) {
274: return true;
275: }
276:
277: for (int index = 0; index < codeAttribute.u4codeLength; index++) {
278: if (oldCode[index] != codeAttribute.code[index]) {
279: return true;
280: }
281: }
282:
283: return false;
284: }
285:
286: private void printChangedCode(Clazz clazz, Method method,
287: CodeAttribute codeAttribute, byte[] oldCode) {
288: System.out.println("Class "
289: + ClassUtil.externalClassName(clazz.getName()));
290: System.out.println("Method "
291: + ClassUtil.externalFullMethodDescription(clazz
292: .getName(), 0, method.getName(clazz), method
293: .getDescriptor(clazz)));
294:
295: for (int index = 0; index < codeAttribute.u4codeLength; index++) {
296: System.out
297: .println((oldCode[index] == codeAttribute.code[index] ? " -- "
298: : " => ")
299: + index
300: + ": "
301: + Integer.toHexString(
302: 0x100 | oldCode[index] & 0xff)
303: .substring(1)
304: + " "
305: + Integer
306: .toHexString(
307: 0x100 | codeAttribute.code[index] & 0xff)
308: .substring(1));
309: }
310: }
311: }
|