📄 checkclassadapter.java
字号:
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2005 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.drools.asm.util;
import java.io.FileInputStream;
import java.io.PrintWriter;
import java.util.List;
import org.drools.asm.AnnotationVisitor;
import org.drools.asm.Attribute;
import org.drools.asm.ClassAdapter;
import org.drools.asm.ClassReader;
import org.drools.asm.ClassVisitor;
import org.drools.asm.FieldVisitor;
import org.drools.asm.MethodVisitor;
import org.drools.asm.Opcodes;
import org.drools.asm.Type;
import org.drools.asm.tree.AbstractInsnNode;
import org.drools.asm.tree.ClassNode;
import org.drools.asm.tree.MethodNode;
import org.drools.asm.tree.TryCatchBlockNode;
import org.drools.asm.tree.analysis.Analyzer;
import org.drools.asm.tree.analysis.Frame;
import org.drools.asm.tree.analysis.SimpleVerifier;
/**
* A {@link ClassAdapter} that checks that its methods are properly used. More
* precisely this class adapter checks each method call individually, based
* <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i>
* of method calls. For example, the invalid sequence
* <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
* "i", "D", null)</tt>
* will <i>not</i> be detected by this class adapter.
*
* @author Eric Bruneton
*/
public class CheckClassAdapter extends ClassAdapter {
/**
* <tt>true</tt> if the visit method has been called.
*/
private boolean start;
/**
* <tt>true</tt> if the visitSource method has been called.
*/
private boolean source;
/**
* <tt>true</tt> if the visitOuterClass method has been called.
*/
private boolean outer;
/**
* <tt>true</tt> if the visitEnd method has been called.
*/
private boolean end;
/**
* Checks a given class. <p> Usage: CheckClassAdapter <fully qualified
* class name or class file name>
*
* @param args the command line arguments.
*
* @throws Exception if the class cannot be found, or if an IO exception
* occurs.
*/
public static void main(final String[] args) throws Exception {
if ( args.length != 1 ) {
System.err.println( "Verifies the given class." );
System.err.println( "Usage: CheckClassAdapter " + "<fully qualified class name or class file name>" );
return;
}
ClassReader cr;
if ( args[0].endsWith( ".class" ) ) {
cr = new ClassReader( new FileInputStream( args[0] ) );
} else {
cr = new ClassReader( args[0] );
}
verify( cr,
false,
new PrintWriter( System.err ) );
}
/**
* Checks a given class
*
* @param cr a <code>ClassReader</code> that contains bytecode for the analysis.
* @param dump true if bytecode should be printed out not only when errors are found.
* @param pw write where results going to be printed
*/
public static void verify(final ClassReader cr,
boolean dump,
final PrintWriter pw) {
final ClassNode cn = new ClassNode();
cr.accept( new CheckClassAdapter( cn ),
true );
final List methods = cn.methods;
for ( int i = 0; i < methods.size(); ++i ) {
final MethodNode method = (MethodNode) methods.get( i );
if ( method.instructions.size() > 0 ) {
final Analyzer a = new Analyzer( new SimpleVerifier( Type.getType( "L" + cn.name + ";" ),
Type.getType( "L" + cn.superName + ";" ),
(cn.access & Opcodes.ACC_INTERFACE) != 0 ) );
try {
a.analyze( cn.name,
method );
if ( !dump ) {
continue;
}
} catch ( final Exception e ) {
e.printStackTrace();
}
final Frame[] frames = a.getFrames();
final TraceMethodVisitor mv = new TraceMethodVisitor();
pw.println( method.name + method.desc );
for ( int j = 0; j < method.instructions.size(); ++j ) {
((AbstractInsnNode) method.instructions.get( j )).accept( mv );
final StringBuffer s = new StringBuffer();
final Frame f = frames[j];
if ( f == null ) {
s.append( '?' );
} else {
for ( int k = 0; k < f.getLocals(); ++k ) {
s.append( getShortName( f.getLocal( k ).toString() ) ).append( ' ' );
}
s.append( " : " );
for ( int k = 0; k < f.getStackSize(); ++k ) {
s.append( getShortName( f.getStack( k ).toString() ) ).append( ' ' );
}
}
while ( s.length() < method.maxStack + method.maxLocals + 1 ) {
s.append( ' ' );
}
pw.print( Integer.toString( j + 100000 ).substring( 1 ) );
pw.print( " " + s + " : " + mv.buf ); // mv.text.get(j));
}
for ( int j = 0; j < method.tryCatchBlocks.size(); ++j ) {
((TryCatchBlockNode) method.tryCatchBlocks.get( j )).accept( mv );
pw.print( " " + mv.buf );
}
pw.println();
}
}
}
private static String getShortName(final String name) {
final int n = name.lastIndexOf( '/' );
int k = name.length();
if ( name.charAt( k - 1 ) == ';' ) {
k--;
}
return n == -1 ? name : name.substring( n + 1,
k );
}
/**
* Constructs a new {@link CheckClassAdapter}.
*
* @param cv the class visitor to which this adapter must delegate calls.
*/
public CheckClassAdapter(final ClassVisitor cv) {
super( cv );
}
// ------------------------------------------------------------------------
// Implementation of the ClassVisitor interface
// ------------------------------------------------------------------------
public void visit(final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces) {
if ( this.start ) {
throw new IllegalStateException( "visit must be called only once" );
} else {
this.start = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -