Browse Source

Add support for the new Dynamic constant (17) created in java 11

tags/rel_3_26_0_ga
Rich Bolen 4 years ago
parent
commit
c08c21ebd2

+ 3
- 3
pom.xml View File

@@ -7,7 +7,7 @@
Javassist (JAVA programming ASSISTant) makes Java bytecode manipulation
simple. It is a class library for editing bytecodes in Java.
</description>
<version>3.25.0-GA</version>
<version>3.25.1-GA</version>
<name>Javassist</name>
<url>http://www.javassist.org/</url>

@@ -151,8 +151,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<source>9</source>
<target>9</target>
<testSource>11</testSource>
<testTarget>11</testTarget>
<testCompilerArgument>-parameters</testCompilerArgument>

+ 19
- 0
src/main/javassist/bytecode/Bytecode.java View File

@@ -1240,6 +1240,25 @@ public class Bytecode extends ByteVector implements Cloneable, Opcode {
growStack(Descriptor.dataSize(desc)); // assume ConstPool#REF_invokeStatic
}

/**
* Appends DYNAMIC.
*
* @param bootstrap an index into the <code>bootstrap_methods</code> array
* of the bootstrap method table.
* @param name the method name.
* @param desc the method descriptor.
* @see Descriptor#ofMethod(CtClass,CtClass[])
* @since 3.17
*/
public void addDynamic(int bootstrap, String name, String desc) {
int nt = constPool.addNameAndTypeInfo(name, desc);
int dyn = constPool.addDynamicInfo(bootstrap, nt);
add(INVOKEDYNAMIC);
addIndex(dyn);
add(0, 0);
growStack(Descriptor.dataSize(desc)); // assume ConstPool#REF_invokeStatic
}

/**
* Appends LDC or LDC_W. The pushed item is a <code>String</code>
* object.

+ 19
- 1
src/main/javassist/bytecode/ClassFileWriter.java View File

@@ -693,13 +693,31 @@ public class ClassFileWriter {
* @since 3.17.1
*/
public int addInvokeDynamicInfo(int bootstrap,
int nameAndTypeInfo) {
int nameAndTypeInfo) {
output.write(InvokeDynamicInfo.tag);
output.writeShort(bootstrap);
output.writeShort(nameAndTypeInfo);
return num++;
}

/**
* Adds a new <code>CONSTANT_InvokeDynamic_info</code>
* structure.
*
* @param bootstrap <code>bootstrap_method_attr_index</code>.
* @param nameAndTypeInfo <code>name_and_type_index</code>.
* @return the index of the added entry.
*
* @since 3.17.1
*/
public int addDynamicInfo(int bootstrap,
int nameAndTypeInfo) {
output.write(DynamicInfo.tag);
output.writeShort(bootstrap);
output.writeShort(nameAndTypeInfo);
return num++;
}

/**
* Adds a new <code>CONSTANT_String_info</code>
* structure.

+ 170
- 47
src/main/javassist/bytecode/ConstPool.java View File

@@ -716,53 +716,99 @@ public final class ConstPool
return mtinfo.descriptor;
}

/**
* Reads the <code>bootstrap_method_attr_index</code> field of the
* <code>CONSTANT_InvokeDynamic_info</code> structure
* at the given index.
*
* @since 3.17
*/
public int getInvokeDynamicBootstrap(int index)
{
InvokeDynamicInfo iv = (InvokeDynamicInfo)getItem(index);
return iv.bootstrap;
}

/**
* Reads the <code>name_and_type_index</code> field of the
* <code>CONSTANT_InvokeDynamic_info</code> structure
* at the given index.
*
* @since 3.17
*/
public int getInvokeDynamicNameAndType(int index)
{
InvokeDynamicInfo iv = (InvokeDynamicInfo)getItem(index);
return iv.nameAndType;
}

/**
* Reads the <code>descriptor_index</code> field of the
* <code>CONSTANT_NameAndType_info</code> structure
* indirectly specified by the given index.
*
* @param index an index to a <code>CONSTANT_InvokeDynamic_info</code>.
* @return the descriptor of the method.
* @since 3.17
*/
public String getInvokeDynamicType(int index)
{
InvokeDynamicInfo iv = (InvokeDynamicInfo)getItem(index);
if (iv == null)
return null;
NameAndTypeInfo n = (NameAndTypeInfo)getItem(iv.nameAndType);
if(n == null)
return null;
return getUtf8Info(n.typeDescriptor);
}

/**
/**
* Reads the <code>bootstrap_method_attr_index</code> field of the
* <code>CONSTANT_InvokeDynamic_info</code> structure
* at the given index.
*
* @since 3.17
*/
public int getInvokeDynamicBootstrap(int index)
{
InvokeDynamicInfo iv = (InvokeDynamicInfo)getItem(index);
return iv.bootstrap;
}

/**
* Reads the <code>name_and_type_index</code> field of the
* <code>CONSTANT_InvokeDynamic_info</code> structure
* at the given index.
*
* @since 3.17
*/
public int getInvokeDynamicNameAndType(int index)
{
InvokeDynamicInfo iv = (InvokeDynamicInfo)getItem(index);
return iv.nameAndType;
}

/**
* Reads the <code>descriptor_index</code> field of the
* <code>CONSTANT_NameAndType_info</code> structure
* indirectly specified by the given index.
*
* @param index an index to a <code>CONSTANT_InvokeDynamic_info</code>.
* @return the descriptor of the method.
* @since 3.17
*/
public String getInvokeDynamicType(int index)
{
InvokeDynamicInfo iv = (InvokeDynamicInfo)getItem(index);
if (iv == null)
return null;
NameAndTypeInfo n = (NameAndTypeInfo)getItem(iv.nameAndType);
if(n == null)
return null;
return getUtf8Info(n.typeDescriptor);
}

/**
* Reads the <code>bootstrap_method_attr_index</code> field of the
* <code>CONSTANT_Dynamic_info</code> structure
* at the given index.
*
* @since 3.17
*/
public int getDynamicBootstrap(int index)
{
DynamicInfo iv = (DynamicInfo)getItem(index);
return iv.bootstrap;
}

/**
* Reads the <code>name_and_type_index</code> field of the
* <code>CONSTANT_Dynamic_info</code> structure
* at the given index.
*
* @since 3.17
*/
public int getDynamicNameAndType(int index)
{
DynamicInfo iv = (DynamicInfo)getItem(index);
return iv.nameAndType;
}

/**
* Reads the <code>descriptor_index</code> field of the
* <code>CONSTANT_NameAndType_info</code> structure
* indirectly specified by the given index.
*
* @param index an index to a <code>CONSTANT_Dynamic_info</code>.
* @return the descriptor of the method.
* @since 3.17
*/
public String getDynamicType(int index)
{
DynamicInfo iv = (DynamicInfo)getItem(index);
if (iv == null)
return null;
NameAndTypeInfo n = (NameAndTypeInfo)getItem(iv.nameAndType);
if(n == null)
return null;
return getUtf8Info(n.typeDescriptor);
}

/**
* Reads the <code>name_index</code> field of the
* <code>CONSTANT_Module_info</code> structure at the given index.
*
@@ -1196,6 +1242,18 @@ public final class ConstPool
}

/**
* Adds a new <code>CONSTANT_InvokeDynamic_info</code> structure.
*
* @param bootstrap <code>bootstrap_method_attr_index</code>.
* @param nameAndType <code>name_and_type_index</code>.
* @return the index of the added entry.
* @since 3.17
*/
public int addDynamicInfo(int bootstrap, int nameAndType) {
return addItem(new DynamicInfo(bootstrap, nameAndType, numOfItems));
}

/**
* Adds a new <code>CONSTANT_Module_info</code>
* @param nameIndex the index of the Utf8 entry.
* @return the index of the added entry.
@@ -1342,6 +1400,9 @@ public final class ConstPool
case MethodTypeInfo.tag : // 16
info = new MethodTypeInfo(in, numOfItems);
break;
case DynamicInfo.tag : // 17
info = new DynamicInfo(in, numOfItems);
break;
case InvokeDynamicInfo.tag : // 18
info = new InvokeDynamicInfo(in, numOfItems);
break;
@@ -2322,6 +2383,68 @@ class InvokeDynamicInfo extends ConstInfo
}
}

class DynamicInfo extends ConstInfo {

static final int tag = 17;
int bootstrap, nameAndType;

public DynamicInfo(int bootstrapMethod,
int ntIndex, int index) {
super(index);
bootstrap = bootstrapMethod;
nameAndType = ntIndex;
}

public DynamicInfo(DataInputStream in, int index)
throws IOException {
super(index);
bootstrap = in.readUnsignedShort();
nameAndType = in.readUnsignedShort();
}

@Override
public int hashCode() {
return (bootstrap << 16) ^ nameAndType;
}

@Override
public boolean equals(Object obj) {
if (obj instanceof DynamicInfo) {
DynamicInfo iv = (DynamicInfo) obj;
return iv.bootstrap == bootstrap
&& iv.nameAndType == nameAndType;
}
return false;
}

@Override
public int getTag() {
return tag;
}

@Override
public int copy(ConstPool src, ConstPool dest,
Map<String, String> map) {
return dest.addDynamicInfo(bootstrap,
src.getItem(nameAndType).copy(src, dest, map));
}

@Override
public void write(DataOutputStream out) throws IOException {
out.writeByte(tag);
out.writeShort(bootstrap);
out.writeShort(nameAndType);
}

@Override
public void print(PrintWriter out) {
out.print("Dynamic #");
out.print(bootstrap);
out.print(", name&type #");
out.println(nameAndType);
}
}

class ModuleInfo extends ConstInfo
{
static final int tag = 19;

+ 36
- 0
src/test/javassist/bytecode/BytecodeTest.java View File

@@ -827,6 +827,42 @@ public class BytecodeTest extends TestCase {
assertEquals("(I)V", cPool2.getUtf8Info(cPool2.getMethodTypeInfo(mtIndex)));
}

// public void testDynamicInfo() throws Exception {
// ClassFile cf = new ClassFile(false, "test4.Dyn", null);
// cf.setInterfaces(new String[] { "java.lang.Cloneable" });
// ConstPool cp = cf.getConstPool();
//
// Bytecode code = new Bytecode(cp, 0, 1);
// code.addAload(0);
// code.addIconst(9);
// code.addLdc("nine");
// code.addDynamic(0, "call", "I");
// code.addOpcode(Opcode.SWAP);
// code.addOpcode(Opcode.POP);
// code.addOpcode(Opcode.IRETURN);
//
// FieldInfo fieldInfo = new FieldInfo(cp, "test", "S");
// fieldInfo.setAccessFlags(AccessFlag.PUBLIC);
// cf.addField(fieldInfo);
//
// String desc
// = "(Ljava/lang/String;)I";
// int mri = cp.addMethodrefInfo(cp.addClassInfo("Dyn"), "boot", desc);
// int mhi = cp.addMethodHandleInfo(ConstPool.REF_invokeStatic, mri);
// int[] args = new int[0];
// BootstrapMethodsAttribute.BootstrapMethod[] bms
// = new BootstrapMethodsAttribute.BootstrapMethod[1];
// bms[0] = new BootstrapMethodsAttribute.BootstrapMethod(mhi, args);
//
// cf.addAttribute(new BootstrapMethodsAttribute(cp, bms));
//
// cf.write(new DataOutputStream(new FileOutputStream("test4/Dyn.class")));
//
// Object obj = make(cf.getName());
//
// assertNotNull(obj);
// }

public static Test suite() {
TestSuite suite = new TestSuite("Bytecode Tests");
suite.addTestSuite(BytecodeTest.class);

+ 22
- 0
src/test/test4/Dyn.java View File

@@ -0,0 +1,22 @@
package test4;

public class Dyn {

public static int test9(int i, String s) {
return 9;
}

public int test8(int i, String s) {
return 8;
}

public static Integer boot(String numberString)
throws NoSuchMethodException, IllegalAccessException {
return Integer.valueOf(numberString);
}

public Integer boot2(String numberString)
throws NoSuchMethodException, IllegalAccessException {
return Integer.valueOf(numberString);
}
}

Loading…
Cancel
Save