📄 generatoradapter.java
字号:
final Label[] labels = new Label[range];
Arrays.fill( labels,
def );
for ( int i = 0; i < len; ++i ) {
labels[keys[i] - min] = newLabel();
}
this.mv.visitTableSwitchInsn( min,
max,
def,
labels );
for ( int i = 0; i < range; ++i ) {
final Label label = labels[i];
if ( label != def ) {
mark( label );
generator.generateCase( i + min,
end );
}
}
} else {
final Label[] labels = new Label[len];
for ( int i = 0; i < len; ++i ) {
labels[i] = newLabel();
}
this.mv.visitLookupSwitchInsn( def,
keys,
labels );
for ( int i = 0; i < len; ++i ) {
mark( labels[i] );
generator.generateCase( keys[i],
end );
}
}
}
mark( def );
generator.generateDefault();
mark( end );
}
/**
* Generates the instruction to return the top stack value to the caller.
*/
public void returnValue() {
this.mv.visitInsn( this.returnType.getOpcode( Opcodes.IRETURN ) );
}
// ------------------------------------------------------------------------
// Instructions to load and store fields
// ------------------------------------------------------------------------
/**
* Generates a get field or set field instruction.
*
* @param opcode the instruction's opcode.
* @param ownerType the class in which the field is defined.
* @param name the name of the field.
* @param fieldType the type of the field.
*/
private void fieldInsn(final int opcode,
final Type ownerType,
final String name,
final Type fieldType) {
this.mv.visitFieldInsn( opcode,
ownerType.getInternalName(),
name,
fieldType.getDescriptor() );
}
/**
* Generates the instruction to push the value of a static field on the
* stack.
*
* @param owner the class in which the field is defined.
* @param name the name of the field.
* @param type the type of the field.
*/
public void getStatic(final Type owner,
final String name,
final Type type) {
fieldInsn( Opcodes.GETSTATIC,
owner,
name,
type );
}
/**
* Generates the instruction to store the top stack value in a static field.
*
* @param owner the class in which the field is defined.
* @param name the name of the field.
* @param type the type of the field.
*/
public void putStatic(final Type owner,
final String name,
final Type type) {
fieldInsn( Opcodes.PUTSTATIC,
owner,
name,
type );
}
/**
* Generates the instruction to push the value of a non static field on the
* stack.
*
* @param owner the class in which the field is defined.
* @param name the name of the field.
* @param type the type of the field.
*/
public void getField(final Type owner,
final String name,
final Type type) {
fieldInsn( Opcodes.GETFIELD,
owner,
name,
type );
}
/**
* Generates the instruction to store the top stack value in a non static
* field.
*
* @param owner the class in which the field is defined.
* @param name the name of the field.
* @param type the type of the field.
*/
public void putField(final Type owner,
final String name,
final Type type) {
fieldInsn( Opcodes.PUTFIELD,
owner,
name,
type );
}
// ------------------------------------------------------------------------
// Instructions to invoke methods
// ------------------------------------------------------------------------
/**
* Generates an invoke method instruction.
*
* @param opcode the instruction's opcode.
* @param type the class in which the method is defined.
* @param method the method to be invoked.
*/
private void invokeInsn(final int opcode,
final Type type,
final Method method) {
final String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName();
this.mv.visitMethodInsn( opcode,
owner,
method.getName(),
method.getDescriptor() );
}
/**
* Generates the instruction to invoke a normal method.
*
* @param owner the class in which the method is defined.
* @param method the method to be invoked.
*/
public void invokeVirtual(final Type owner,
final Method method) {
invokeInsn( Opcodes.INVOKEVIRTUAL,
owner,
method );
}
/**
* Generates the instruction to invoke a constructor.
*
* @param type the class in which the constructor is defined.
* @param method the constructor to be invoked.
*/
public void invokeConstructor(final Type type,
final Method method) {
invokeInsn( Opcodes.INVOKESPECIAL,
type,
method );
}
/**
* Generates the instruction to invoke a static method.
*
* @param owner the class in which the method is defined.
* @param method the method to be invoked.
*/
public void invokeStatic(final Type owner,
final Method method) {
invokeInsn( Opcodes.INVOKESTATIC,
owner,
method );
}
/**
* Generates the instruction to invoke an interface method.
*
* @param owner the class in which the method is defined.
* @param method the method to be invoked.
*/
public void invokeInterface(final Type owner,
final Method method) {
invokeInsn( Opcodes.INVOKEINTERFACE,
owner,
method );
}
// ------------------------------------------------------------------------
// Instructions to create objects and arrays
// ------------------------------------------------------------------------
/**
* Generates a type dependent instruction.
*
* @param opcode the instruction's opcode.
* @param type the instruction's operand.
*/
private void typeInsn(final int opcode,
final Type type) {
String desc;
if ( type.getSort() == Type.ARRAY ) {
desc = type.getDescriptor();
} else {
desc = type.getInternalName();
}
this.mv.visitTypeInsn( opcode,
desc );
}
/**
* Generates the instruction to create a new object.
*
* @param type the class of the object to be created.
*/
public void newInstance(final Type type) {
typeInsn( Opcodes.NEW,
type );
}
/**
* Generates the instruction to create a new array.
*
* @param type the type of the array elements.
*/
public void newArray(final Type type) {
int typ;
switch ( type.getSort() ) {
case Type.BOOLEAN :
typ = Opcodes.T_BOOLEAN;
break;
case Type.CHAR :
typ = Opcodes.T_CHAR;
break;
case Type.BYTE :
typ = Opcodes.T_BYTE;
break;
case Type.SHORT :
typ = Opcodes.T_SHORT;
break;
case Type.INT :
typ = Opcodes.T_INT;
break;
case Type.FLOAT :
typ = Opcodes.T_FLOAT;
break;
case Type.LONG :
typ = Opcodes.T_LONG;
break;
case Type.DOUBLE :
typ = Opcodes.T_DOUBLE;
break;
default :
typeInsn( Opcodes.ANEWARRAY,
type );
return;
}
this.mv.visitIntInsn( Opcodes.NEWARRAY,
typ );
}
// ------------------------------------------------------------------------
// Miscelaneous instructions
// ------------------------------------------------------------------------
/**
* Generates the instruction to compute the length of an array.
*/
public void arrayLength() {
this.mv.visitInsn( Opcodes.ARRAYLENGTH );
}
/**
* Generates the instruction to throw an exception.
*/
public void throwException() {
this.mv.visitInsn( Opcodes.ATHROW );
}
/**
* Generates the instructions to create and throw an exception. The
* exception class must have a constructor with a single String argument.
*
* @param type the class of the exception to be thrown.
* @param msg the detailed message of the exception.
*/
public void throwException(final Type type,
final String msg) {
newInstance( type );
dup();
push( msg );
invokeConstructor( type,
Method.getMethod( "void <init> (String)" ) );
throwException();
}
/**
* Generates the instruction to check that the top stack value is of the
* given type.
*
* @param type a class or interface type.
*/
public void checkCast(final Type type) {
if ( !type.equals( GeneratorAdapter.OBJECT_TYPE ) ) {
typeInsn( Opcodes.CHECKCAST,
type );
}
}
/**
* Generates the instruction to test if the top stack value is of the given
* type.
*
* @param type a class or interface type.
*/
public void instanceOf(final Type type) {
typeInsn( Opcodes.INSTANCEOF,
type );
}
/**
* Generates the instruction to get the monitor of the top stack value.
*/
public void monitorEnter() {
this.mv.visitInsn( Opcodes.MONITORENTER );
}
/**
* Generates the instruction to release the monitor of the top stack value.
*/
public void monitorExit() {
this.mv.visitInsn( Opcodes.MONITOREXIT );
}
// ------------------------------------------------------------------------
// Non instructions
// ------------------------------------------------------------------------
/**
* Marks the end of the visited method.
*/
public void endMethod() {
if ( (this.access & Opcodes.ACC_ABSTRACT) == 0 ) {
this.mv.visitMaxs( 0,
0 );
}
}
/**
* Marks the start of an exception handler.
*
* @param start beginning of the exception handler's scope (inclusive).
* @param end end of the exception handler's scope (exclusive).
* @param exception internal name of the type of exceptions handled by the
* handler.
*/
public void catchException(final Label start,
final Label end,
final Type exception) {
this.mv.visitTryCatchBlock( start,
end,
mark(),
exception.getInternalName() );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -