Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JASSIST-270: Add support for the new Dynamic constant (17) created in java 11 #272

Merged
merged 6 commits into from Aug 31, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions pom.xml
Expand Up @@ -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>

Expand Down Expand Up @@ -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>
richbolen marked this conversation as resolved.
Show resolved Hide resolved
<testSource>11</testSource>
<testTarget>11</testTarget>
<testCompilerArgument>-parameters</testCompilerArgument>
Expand Down
19 changes: 19 additions & 0 deletions src/main/javassist/bytecode/Bytecode.java
Expand Up @@ -1240,6 +1240,25 @@ public void addInvokedynamic(int bootstrap, String name, String desc) {
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);
richbolen marked this conversation as resolved.
Show resolved Hide resolved
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.
Expand Down
20 changes: 19 additions & 1 deletion src/main/javassist/bytecode/ClassFileWriter.java
Expand Up @@ -693,13 +693,31 @@ public int addMethodTypeInfo(int desc) {
* @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,
richbolen marked this conversation as resolved.
Show resolved Hide resolved
int nameAndTypeInfo) {
output.write(DynamicInfo.tag);
output.writeShort(bootstrap);
output.writeShort(nameAndTypeInfo);
return num++;
}

/**
* Adds a new <code>CONSTANT_String_info</code>
* structure.
Expand Down
217 changes: 170 additions & 47 deletions src/main/javassist/bytecode/ConstPool.java
Expand Up @@ -716,53 +716,99 @@ public int getMethodTypeInfo(int index)
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.
*
Expand Down Expand Up @@ -1196,6 +1242,18 @@ public int addInvokeDynamicInfo(int bootstrap, int nameAndType)
}

/**
* Adds a new <code>CONSTANT_InvokeDynamic_info</code> structure.
richbolen marked this conversation as resolved.
Show resolved Hide resolved
*
* @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.
Expand Down Expand Up @@ -1342,6 +1400,9 @@ private int readOne(DataInputStream in) throws IOException
case MethodTypeInfo.tag : // 16
info = new MethodTypeInfo(in, numOfItems);
break;
case DynamicInfo.tag : // 17
richbolen marked this conversation as resolved.
Show resolved Hide resolved
info = new DynamicInfo(in, numOfItems);
break;
case InvokeDynamicInfo.tag : // 18
info = new InvokeDynamicInfo(in, numOfItems);
break;
Expand Down Expand Up @@ -2322,6 +2383,68 @@ public void print(PrintWriter out) {
}
}

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;
Expand Down
36 changes: 36 additions & 0 deletions src/test/javassist/bytecode/BytecodeTest.java
Expand Up @@ -827,6 +827,42 @@ public void testInvokeDynamic() throws Exception {
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);
// }

richbolen marked this conversation as resolved.
Show resolved Hide resolved
public static Test suite() {
TestSuite suite = new TestSuite("Bytecode Tests");
suite.addTestSuite(BytecodeTest.class);
Expand Down
22 changes: 22 additions & 0 deletions src/test/test4/Dyn.java
@@ -0,0 +1,22 @@
package test4;

public class Dyn {
richbolen marked this conversation as resolved.
Show resolved Hide resolved

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);
}
}