📄 classwriter.java
字号:
return out.data;
}
// ------------------------------------------------------------------------
// Utility methods: constant pool management
// ------------------------------------------------------------------------
/**
* Adds a number or string constant to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
*
* @param cst the value of the constant to be added to the constant pool.
* This parameter must be an {@link Integer}, a {@link Float}, a
* {@link Long}, a {@link Double}, a {@link String} or a
* {@link Type}.
* @return a new or already existing constant item with the given value.
*/
Item newConstItem(final Object cst) {
if ( cst instanceof Integer ) {
final int val = ((Integer) cst).intValue();
return newInteger( val );
} else if ( cst instanceof Byte ) {
final int val = ((Byte) cst).intValue();
return newInteger( val );
} else if ( cst instanceof Character ) {
final int val = ((Character) cst).charValue();
return newInteger( val );
} else if ( cst instanceof Short ) {
final int val = ((Short) cst).intValue();
return newInteger( val );
} else if ( cst instanceof Boolean ) {
final int val = ((Boolean) cst).booleanValue() ? 1 : 0;
return newInteger( val );
} else if ( cst instanceof Float ) {
final float val = ((Float) cst).floatValue();
return newFloat( val );
} else if ( cst instanceof Long ) {
final long val = ((Long) cst).longValue();
return newLong( val );
} else if ( cst instanceof Double ) {
final double val = ((Double) cst).doubleValue();
return newDouble( val );
} else if ( cst instanceof String ) {
return newString( (String) cst );
} else if ( cst instanceof Type ) {
final Type t = (Type) cst;
return newClassItem( t.getSort() == Type.OBJECT ? t.getInternalName() : t.getDescriptor() );
} else {
throw new IllegalArgumentException( "value " + cst );
}
}
/**
* Adds a number or string constant to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param cst the value of the constant to be added to the constant pool.
* This parameter must be an {@link Integer}, a {@link Float}, a
* {@link Long}, a {@link Double} or a {@link String}.
* @return the index of a new or already existing constant item with the
* given value.
*/
public int newConst(final Object cst) {
return newConstItem( cst ).index;
}
/**
* Adds an UTF8 string to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param value the String value.
* @return the index of a new or already existing UTF8 item.
*/
public int newUTF8(final String value) {
this.key.set( ClassWriter.UTF8,
value,
null,
null );
Item result = get( this.key );
if ( result == null ) {
this.pool.putByte( ClassWriter.UTF8 ).putUTF8( value );
result = new Item( this.index++,
this.key );
put( result );
}
return result.index;
}
/**
* Adds a class reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param value the internal name of the class.
* @return the index of a new or already existing class reference item.
*/
public int newClass(final String value) {
return newClassItem( value ).index;
}
/**
* Adds a class reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param value the internal name of the class.
* @return a new or already existing class reference item.
*/
private Item newClassItem(final String value) {
this.key2.set( ClassWriter.CLASS,
value,
null,
null );
Item result = get( this.key2 );
if ( result == null ) {
this.pool.put12( ClassWriter.CLASS,
newUTF8( value ) );
result = new Item( this.index++,
this.key2 );
put( result );
}
return result;
}
/**
* Adds a field reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param owner the internal name of the field's owner class.
* @param name the field's name.
* @param desc the field's descriptor.
* @return the index of a new or already existing field reference item.
*/
public int newField(final String owner,
final String name,
final String desc) {
this.key3.set( ClassWriter.FIELD,
owner,
name,
desc );
Item result = get( this.key3 );
if ( result == null ) {
put122( ClassWriter.FIELD,
newClass( owner ),
newNameType( name,
desc ) );
result = new Item( this.index++,
this.key3 );
put( result );
}
return result.index;
}
/**
* Adds a method reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
*
* @param owner the internal name of the method's owner class.
* @param name the method's name.
* @param desc the method's descriptor.
* @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
* @return a new or already existing method reference item.
*/
Item newMethodItem(final String owner,
final String name,
final String desc,
final boolean itf) {
final int type = itf ? ClassWriter.IMETH : ClassWriter.METH;
this.key3.set( type,
owner,
name,
desc );
Item result = get( this.key3 );
if ( result == null ) {
put122( type,
newClass( owner ),
newNameType( name,
desc ) );
result = new Item( this.index++,
this.key3 );
put( result );
}
return result;
}
/**
* Adds a method reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param owner the internal name of the method's owner class.
* @param name the method's name.
* @param desc the method's descriptor.
* @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
* @return the index of a new or already existing method reference item.
*/
public int newMethod(final String owner,
final String name,
final String desc,
final boolean itf) {
return newMethodItem( owner,
name,
desc,
itf ).index;
}
/**
* Adds an integer to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item.
*
* @param value the int value.
* @return a new or already existing int item.
*/
Item newInteger(final int value) {
this.key.set( value );
Item result = get( this.key );
if ( result == null ) {
this.pool.putByte( ClassWriter.INT ).putInt( value );
result = new Item( this.index++,
this.key );
put( result );
}
return result;
}
/**
* Adds a float to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
*
* @param value the float value.
* @return a new or already existing float item.
*/
Item newFloat(final float value) {
this.key.set( value );
Item result = get( this.key );
if ( result == null ) {
this.pool.putByte( ClassWriter.FLOAT ).putInt( Float.floatToIntBits( value ) );
result = new Item( this.index++,
this.key );
put( result );
}
return result;
}
/**
* Adds a long to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
*
* @param value the long value.
* @return a new or already existing long item.
*/
Item newLong(final long value) {
this.key.set( value );
Item result = get( this.key );
if ( result == null ) {
this.pool.putByte( ClassWriter.LONG ).putLong( value );
result = new Item( this.index,
this.key );
put( result );
this.index += 2;
}
return result;
}
/**
* Adds a double to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
*
* @param value the double value.
* @return a new or already existing double item.
*/
Item newDouble(final double value) {
this.key.set( value );
Item result = get( this.key );
if ( result == null ) {
this.pool.putByte( ClassWriter.DOUBLE ).putLong( Double.doubleToLongBits( value ) );
result = new Item( this.index,
this.key );
put( result );
this.index += 2;
}
return result;
}
/**
* Adds a string to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
*
* @param value the String value.
* @return a new or already existing string item.
*/
private Item newString(final String value) {
this.key2.set( ClassWriter.STR,
value,
null,
null );
Item result = get( this.key2 );
if ( result == null ) {
this.pool.put12( ClassWriter.STR,
newUTF8( value ) );
result = new Item( this.index++,
this.key2 );
put( result );
}
return result;
}
/**
* Adds a name and type to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param name a name.
* @param desc a type descriptor.
* @return the index of a new or already existing name and type item.
*/
public int newNameType(final String name,
final String desc) {
this.key2.set( ClassWriter.NAME_TYPE,
name,
desc,
null );
Item result = get( this.key2 );
if ( result == null ) {
put122( ClassWriter.NAME_TYPE,
newUTF8( name ),
newUTF8( desc ) );
result = new Item( this.index++,
this.key2 );
put( result );
}
return result.index;
}
/**
* Returns the constant pool's hash table item which is equal to the given
* item.
*
* @param key a constant pool item.
* @return the constant pool's hash table item which is equal to the given
* item, or <tt>null</tt> if there is no such item.
*/
private Item get(final Item key) {
Item i = this.items[key.hashCode % this.items.length];
while ( i != null && !key.isEqualTo( i ) ) {
i = i.next;
}
return i;
}
/**
* Puts the given item in the constant pool's hash table. The hash table
* <i>must</i> not already contains this item.
*
* @param i the item to be added to the constant pool's hash table.
*/
private void put(final Item i) {
if ( this.index > this.threshold ) {
final int ll = this.items.length;
final int nl = ll * 2 + 1;
final Item[] newItems = new Item[nl];
for ( int l = ll - 1; l >= 0; --l ) {
Item j = this.items[l];
while ( j != null ) {
final int index = j.hashCode % newItems.length;
final Item k = j.next;
j.next = newItems[index];
newItems[index] = j;
j = k;
}
}
this.items = newItems;
this.threshold = (int) (nl * 0.75);
}
final int index = i.hashCode % this.items.length;
i.next = this.items[index];
this.items[index] = i;
}
/**
* Puts one byte and two shorts into the constant pool.
*
* @param b a byte.
* @param s1 a short.
* @param s2 another short.
*/
private void put122(final int b,
final int s1,
final int s2) {
this.pool.put12( b,
s1 ).putShort( s2 );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -