• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // ASM: a very small and fast Java bytecode manipulation framework
2 // Copyright (c) 2000-2011 INRIA, France Telecom
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions
7 // are met:
8 // 1. Redistributions of source code must retain the above copyright
9 //    notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 //    notice, this list of conditions and the following disclaimer in the
12 //    documentation and/or other materials provided with the distribution.
13 // 3. Neither the name of the copyright holders nor the names of its
14 //    contributors may be used to endorse or promote products derived from
15 //    this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 // THE POSSIBILITY OF SUCH DAMAGE.
28 package org.objectweb.asm.util;
29 
30 import java.io.PrintWriter;
31 import org.objectweb.asm.AnnotationVisitor;
32 import org.objectweb.asm.Attribute;
33 import org.objectweb.asm.ClassVisitor;
34 import org.objectweb.asm.FieldVisitor;
35 import org.objectweb.asm.MethodVisitor;
36 import org.objectweb.asm.ModuleVisitor;
37 import org.objectweb.asm.Opcodes;
38 import org.objectweb.asm.RecordComponentVisitor;
39 import org.objectweb.asm.TypePath;
40 
41 /**
42  * A {@link ClassVisitor} that prints the classes it visits with a {@link Printer}. This class
43  * visitor can be used in the middle of a class visitor chain to trace the class that is visited at
44  * a given point in this chain. This may be useful for debugging purposes.
45  *
46  * <p>When used with a {@link Textifier}, the trace printed when visiting the {@code Hello} class is
47  * the following:
48  *
49  * <pre>
50  * // class version 49.0 (49) // access flags 0x21 public class Hello {
51  *
52  * // compiled from: Hello.java
53  *
54  * // access flags 0x1
55  * public &lt;init&gt; ()V
56  * ALOAD 0
57  * INVOKESPECIAL java/lang/Object &lt;init&gt; ()V
58  * RETURN
59  * MAXSTACK = 1 MAXLOCALS = 1
60  *
61  * // access flags 0x9
62  * public static main ([Ljava/lang/String;)V
63  * GETSTATIC java/lang/System out Ljava/io/PrintStream;
64  * LDC &quot;hello&quot;
65  * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V
66  * RETURN
67  * MAXSTACK = 2 MAXLOCALS = 1
68  * }
69  * </pre>
70  *
71  * <p>where {@code Hello} is defined by:
72  *
73  * <pre>
74  * public class Hello {
75  *
76  *   public static void main(String[] args) {
77  *     System.out.println(&quot;hello&quot;);
78  *   }
79  * }
80  * </pre>
81  *
82  * @author Eric Bruneton
83  * @author Eugene Kuleshov
84  */
85 public final class TraceClassVisitor extends ClassVisitor {
86 
87   /** The print writer to be used to print the class. May be {@literal null}. */
88   private final PrintWriter printWriter;
89 
90   /** The printer to convert the visited class into text. */
91   // DontCheck(MemberName): can't be renamed (for backward binary compatibility).
92   public final Printer p;
93 
94   /**
95    * Constructs a new {@link TraceClassVisitor}.
96    *
97    * @param printWriter the print writer to be used to print the class. May be {@literal null}.
98    */
TraceClassVisitor(final PrintWriter printWriter)99   public TraceClassVisitor(final PrintWriter printWriter) {
100     this(null, printWriter);
101   }
102 
103   /**
104    * Constructs a new {@link TraceClassVisitor}.
105    *
106    * @param classVisitor the class visitor to which to delegate calls. May be {@literal null}.
107    * @param printWriter the print writer to be used to print the class. May be {@literal null}.
108    */
TraceClassVisitor(final ClassVisitor classVisitor, final PrintWriter printWriter)109   public TraceClassVisitor(final ClassVisitor classVisitor, final PrintWriter printWriter) {
110     this(classVisitor, new Textifier(), printWriter);
111   }
112 
113   /**
114    * Constructs a new {@link TraceClassVisitor}.
115    *
116    * @param classVisitor the class visitor to which to delegate calls. May be {@literal null}.
117    * @param printer the printer to convert the visited class into text.
118    * @param printWriter the print writer to be used to print the class. May be {@literal null}.
119    */
TraceClassVisitor( final ClassVisitor classVisitor, final Printer printer, final PrintWriter printWriter)120   public TraceClassVisitor(
121       final ClassVisitor classVisitor, final Printer printer, final PrintWriter printWriter) {
122     super(/* latest api = */ Opcodes.ASM10_EXPERIMENTAL, classVisitor);
123     this.printWriter = printWriter;
124     this.p = printer;
125   }
126 
127   @Override
visit( final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)128   public void visit(
129       final int version,
130       final int access,
131       final String name,
132       final String signature,
133       final String superName,
134       final String[] interfaces) {
135     p.visit(version, access, name, signature, superName, interfaces);
136     super.visit(version, access, name, signature, superName, interfaces);
137   }
138 
139   @Override
visitSource(final String file, final String debug)140   public void visitSource(final String file, final String debug) {
141     p.visitSource(file, debug);
142     super.visitSource(file, debug);
143   }
144 
145   @Override
visitModule(final String name, final int flags, final String version)146   public ModuleVisitor visitModule(final String name, final int flags, final String version) {
147     Printer modulePrinter = p.visitModule(name, flags, version);
148     return new TraceModuleVisitor(super.visitModule(name, flags, version), modulePrinter);
149   }
150 
151   @Override
visitNestHost(final String nestHost)152   public void visitNestHost(final String nestHost) {
153     p.visitNestHost(nestHost);
154     super.visitNestHost(nestHost);
155   }
156 
157   @Override
visitOuterClass(final String owner, final String name, final String descriptor)158   public void visitOuterClass(final String owner, final String name, final String descriptor) {
159     p.visitOuterClass(owner, name, descriptor);
160     super.visitOuterClass(owner, name, descriptor);
161   }
162 
163   @Override
visitAnnotation(final String descriptor, final boolean visible)164   public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
165     Printer annotationPrinter = p.visitClassAnnotation(descriptor, visible);
166     return new TraceAnnotationVisitor(
167         super.visitAnnotation(descriptor, visible), annotationPrinter);
168   }
169 
170   @Override
visitTypeAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)171   public AnnotationVisitor visitTypeAnnotation(
172       final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
173     Printer annotationPrinter = p.visitClassTypeAnnotation(typeRef, typePath, descriptor, visible);
174     return new TraceAnnotationVisitor(
175         super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter);
176   }
177 
178   @Override
visitAttribute(final Attribute attribute)179   public void visitAttribute(final Attribute attribute) {
180     p.visitClassAttribute(attribute);
181     super.visitAttribute(attribute);
182   }
183 
184   @Override
visitNestMember(final String nestMember)185   public void visitNestMember(final String nestMember) {
186     p.visitNestMember(nestMember);
187     super.visitNestMember(nestMember);
188   }
189 
190   @Override
visitPermittedSubclass(final String permittedSubclass)191   public void visitPermittedSubclass(final String permittedSubclass) {
192     p.visitPermittedSubclass(permittedSubclass);
193     super.visitPermittedSubclass(permittedSubclass);
194   }
195 
196   @Override
visitInnerClass( final String name, final String outerName, final String innerName, final int access)197   public void visitInnerClass(
198       final String name, final String outerName, final String innerName, final int access) {
199     p.visitInnerClass(name, outerName, innerName, access);
200     super.visitInnerClass(name, outerName, innerName, access);
201   }
202 
203   @Override
visitRecordComponent( final String name, final String descriptor, final String signature)204   public RecordComponentVisitor visitRecordComponent(
205       final String name, final String descriptor, final String signature) {
206     Printer recordComponentPrinter = p.visitRecordComponent(name, descriptor, signature);
207     return new TraceRecordComponentVisitor(
208         super.visitRecordComponent(name, descriptor, signature), recordComponentPrinter);
209   }
210 
211   @Override
visitField( final int access, final String name, final String descriptor, final String signature, final Object value)212   public FieldVisitor visitField(
213       final int access,
214       final String name,
215       final String descriptor,
216       final String signature,
217       final Object value) {
218     Printer fieldPrinter = p.visitField(access, name, descriptor, signature, value);
219     return new TraceFieldVisitor(
220         super.visitField(access, name, descriptor, signature, value), fieldPrinter);
221   }
222 
223   @Override
visitMethod( final int access, final String name, final String descriptor, final String signature, final String[] exceptions)224   public MethodVisitor visitMethod(
225       final int access,
226       final String name,
227       final String descriptor,
228       final String signature,
229       final String[] exceptions) {
230     Printer methodPrinter = p.visitMethod(access, name, descriptor, signature, exceptions);
231     return new TraceMethodVisitor(
232         super.visitMethod(access, name, descriptor, signature, exceptions), methodPrinter);
233   }
234 
235   @Override
visitEnd()236   public void visitEnd() {
237     p.visitClassEnd();
238     if (printWriter != null) {
239       p.print(printWriter);
240       printWriter.flush();
241     }
242     super.visitEnd();
243   }
244 }
245