]> source.dussan.org Git - javassist.git/commitdiff
Add support for the new Dynamic constant (17) created in java 11
authorRich Bolen <rich.bolen@icg360.com>
Tue, 20 Aug 2019 14:52:01 +0000 (10:52 -0400)
committerRich Bolen <rich.bolen@icg360.com>
Tue, 20 Aug 2019 14:52:01 +0000 (10:52 -0400)
pom.xml
src/main/javassist/bytecode/Bytecode.java
src/main/javassist/bytecode/ClassFileWriter.java
src/main/javassist/bytecode/ConstPool.java
src/test/javassist/bytecode/BytecodeTest.java
src/test/test4/Dyn.java [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index c3bd1990e69bf72b8f503442ea7365cc78c824b7..fc8e2fdfb13ddc7cef2f8edb19a3fcfaa94f85ca 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -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>
 
         <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>
index 37a6d127ffc07f83957cfbf8fadb20a09f594e5f..193e3f8a8925ae75b157d5cf6a43683dda2fac85 100644 (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.
index 931ffcb48670121af6b77d536ef67c32eb121c52..03650b75e578c766b982017b2f23e16457c68940 100644 (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.
index 0447ece7aa069424f2e067a7d02c3481a4796191..089850893352826c5f4333265840c4ae6f67621b 100644 (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;
index 5ddf5d5bdea6ddaa986c03dbe0f9796ff2208424..ec754b56b9b28a96222a92edc0a2944a413aaa37 100644 (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);
diff --git a/src/test/test4/Dyn.java b/src/test/test4/Dyn.java
new file mode 100644 (file)
index 0000000..83418d4
--- /dev/null
@@ -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);
+  }
+}