[Git][java-team/javassist][upstream] New upstream version 3.26.0

Emmanuel Bourg gitlab at salsa.debian.org
Mon Jan 27 09:17:49 GMT 2020



Emmanuel Bourg pushed to branch upstream at Debian Java Maintainers / javassist


Commits:
1b81f146 by Emmanuel Bourg at 2020-01-27T10:14:16+01:00
New upstream version 3.26.0
- - - - -


20 changed files:

- Readme.html
- build.xml
- pom.xml
- src/main/META-INF/MANIFEST.MF
- src/main/javassist/ClassPool.java
- src/main/javassist/ClassPoolTail.java
- src/main/javassist/CtBehavior.java
- src/main/javassist/CtClass.java
- src/main/javassist/bytecode/ClassFileWriter.java
- src/main/javassist/bytecode/CodeIterator.java
- src/main/javassist/bytecode/ConstPool.java
- src/main/javassist/compiler/MemberCodeGen.java
- src/main/javassist/compiler/MemberResolver.java
- src/main/javassist/util/proxy/ProxyFactory.java
- src/test/Test.java
- src/test/javassist/JvstTest5.java
- + src/test/javassist/proxyfactory/GenSig.java
- src/test/javassist/proxyfactory/ProxyFactoryTest.java
- + src/test/test5/InsertAfter.java
- + src/test/test5/NestHost4.java


Changes:

=====================================
Readme.html
=====================================
@@ -281,6 +281,11 @@ see javassist.Dump.
 
 <h2>Changes</h2>
 
+<p>-version 3.26 on October 3, 2019
+<ul>
+   <li>GitHub Issue #270 (PR #272), #265 (PR #267), #271, #222, and #275.
+</ul>
+
 <p>-version 3.25 on April 16, 2019
 <ul>
     <li>GitHub Issue #72 (PR #231), #241, #242 (PR #243), PR #244,


=====================================
build.xml
=====================================
@@ -6,7 +6,7 @@
 
 <project name="javassist" default="jar" basedir=".">
 
-  <property name="dist-version" value="javassist-3.25.0-GA"/>
+  <property name="dist-version" value="javassist-3.26.0-GA"/>
 
   <property environment="env"/>
   <property name="target.jar" value="javassist.jar"/>
@@ -79,8 +79,8 @@
            destdir="${build.classes.dir}"
            debug="on"
            deprecation="on"
-	       source="1.7"
-	       target="1.7"
+	       source="1.8"
+	       target="1.8"
            optimize="off"
     	   includeantruntime="true"
            includes="**">


=====================================
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.26.0-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>1.8</source>
+          <target>1.8</target>
           <testSource>11</testSource>
           <testTarget>11</testTarget>
           <testCompilerArgument>-parameters</testCompilerArgument>


=====================================
src/main/META-INF/MANIFEST.MF
=====================================
@@ -1,5 +1,5 @@
 Specification-Title: Javassist
 Specification-Vendor: Shigeru Chiba, www.javassist.org
-Specification-Version: 3.25.0-GA
+Specification-Version: 3.26.0-GA
 Main-Class: javassist.CtClass
 Automatic-Module-Name: org.javassist


=====================================
src/main/javassist/ClassPool.java
=====================================
@@ -113,6 +113,14 @@ public class ClassPool {
      */
     public static boolean releaseUnmodifiedClassFile = true;
 
+    /**
+     * If true, the contents of a jar file are cached after the jar
+     * file is opened.
+     *
+     * <p>The initial value is true.
+     */
+    public static boolean cacheOpenedJarFile = true;    // see ClassPoolTail.JarClassPath#openClassfile(String)
+
     protected ClassPoolTail source;
     protected ClassPool parent;
     protected Hashtable classes;        // should be synchronous


=====================================
src/main/javassist/ClassPoolTail.java
=====================================
@@ -159,9 +159,13 @@ final class JarClassPath implements ClassPath {
         URL jarURL = find(classname);
         if (null != jarURL)
             try {
-                java.net.URLConnection con = jarURL.openConnection();
-                con.setUseCaches(false);
-                return con.getInputStream();
+                if (ClassPool.cacheOpenedJarFile)
+                    return jarURL.openConnection().getInputStream();
+                else {
+                    java.net.URLConnection con = jarURL.openConnection();
+                    con.setUseCaches(false);
+                    return con.getInputStream();
+                }
             }
             catch (IOException e) {
                 throw new NotFoundException("broken jar file?: "


=====================================
src/main/javassist/CtBehavior.java
=====================================
@@ -812,7 +812,7 @@ public abstract class CtBehavior extends CtMember {
 
     /**
      * Inserts bytecode at the end of the body.
-     * The bytecode is inserted just before every return insturction.
+     * The bytecode is inserted just before every return instruction.
      * It is not executed when an exception is thrown.
      *
      * @param src       the source code representing the inserted bytecode.
@@ -821,12 +821,12 @@ public abstract class CtBehavior extends CtMember {
     public void insertAfter(String src)
         throws CannotCompileException
     {
-        insertAfter(src, false);
+        insertAfter(src, false, false);
     }
 
     /**
      * Inserts bytecode at the end of the body.
-     * The bytecode is inserted just before every return insturction.
+     * The bytecode is inserted just before every return instruction.
      *
      * @param src       the source code representing the inserted bytecode.
      *                  It must be a single statement or block.
@@ -838,6 +838,35 @@ public abstract class CtBehavior extends CtMember {
      */
     public void insertAfter(String src, boolean asFinally)
         throws CannotCompileException
+    {
+        insertAfter(src, asFinally, false);
+    }
+
+    /**
+     * Inserts bytecode at the end of the body.
+     * The bytecode is inserted just before every return instruction.
+     *
+     * @param src       the source code representing the inserted bytecode.
+     *                  It must be a single statement or block.
+     * @param asFinally         true if the inserted bytecode is executed
+     *                  not only when the control normally returns
+     *                  but also when an exception is thrown.
+     *                  If this parameter is true, the inserted code cannot
+     *                  access local variables.
+     * @param redundant if true, redundant bytecode will be generated.
+     *                  the redundancy is necessary when some compilers (Kotlin?)
+     *                  generate the original bytecode.
+     *                  The other <code>insertAfter</code> methods calls this method
+     *                  with <code>false</code> for this parameter.
+     *                  A tip is to pass <code>this.getDeclaringClass().isKotlin()</code>
+     *                  to this parameter.
+     *
+     * @see CtClass#isKotlin()
+     * @see #getDeclaringClass()
+     * @since 3.26
+     */
+    public void insertAfter(String src, boolean asFinally, boolean redundant)
+        throws CannotCompileException
     {
         CtClass cc = declaringClass;
         cc.checkModify();
@@ -878,18 +907,50 @@ public abstract class CtBehavior extends CtMember {
                 if (c == Opcode.ARETURN || c == Opcode.IRETURN
                     || c == Opcode.FRETURN || c == Opcode.LRETURN
                     || c == Opcode.DRETURN || c == Opcode.RETURN) {
-                    if (noReturn) {
-                        // finally clause for normal termination
-                        adviceLen = insertAfterAdvice(b, jv, src, pool, rtype, varNo);
-                        handlerPos = iterator.append(b.get());
-                        iterator.append(b.getExceptionTable(), handlerPos);
+                    if (redundant) {
+                        iterator.setMark2(handlerPos);
+                        Bytecode bcode;
+                        Javac jvc;
+                        int retVarNo;
+                        if (noReturn) {
+                            noReturn = false;
+                            bcode = b;
+                            jvc = jv;
+                            retVarNo = varNo;
+                        }
+                        else {
+                            bcode = new Bytecode(pool, 0, retAddr + 1);
+                            bcode.setStackDepth(ca.getMaxStack() + 1);
+                            jvc = new Javac(bcode, cc);
+                            int nvars2 = jvc.recordParams(getParameterTypes(),
+                                                          Modifier.isStatic(getModifiers()));
+                            jvc.recordParamNames(ca, nvars2);
+                            retVarNo = jvc.recordReturnType(rtype, true);
+                            jvc.recordLocalVariables(ca, 0);
+                        }
+
+                        int adviceLen2 = insertAfterAdvice(bcode, jvc, src, pool, rtype, retVarNo);
+                        int offset = iterator.append(bcode.get());
+                        iterator.append(bcode.getExceptionTable(), offset);
+                        int advicePos2 = iterator.getCodeLength() - adviceLen2;
+                        insertGoto(iterator, advicePos2, pos);
+                        handlerPos = iterator.getMark2();
+                    }
+                    else {
+                        if (noReturn) {
+                            // finally clause for normal termination
+                            adviceLen = insertAfterAdvice(b, jv, src, pool, rtype, varNo);
+                            handlerPos = iterator.append(b.get());
+                            iterator.append(b.getExceptionTable(), handlerPos);
+                            advicePos = iterator.getCodeLength() - adviceLen;
+                            handlerLen = advicePos - handlerPos;
+                            noReturn = false;
+                        }
+
+                        insertGoto(iterator, advicePos, pos);
                         advicePos = iterator.getCodeLength() - adviceLen;
-                        handlerLen = advicePos - handlerPos;
-                        noReturn = false;
+                        handlerPos = advicePos - handlerLen;
                     }
-                    insertGoto(iterator, advicePos, pos);
-                    advicePos = iterator.getCodeLength() - adviceLen;
-                    handlerPos = advicePos - handlerLen;
                 }
             }
 


=====================================
src/main/javassist/CtClass.java
=====================================
@@ -69,7 +69,7 @@ public abstract class CtClass {
     /**
      * The version number of this release.
      */
-    public static final String version = "3.25.0-GA";
+    public static final String version = "3.26.0-GA";
 
     /**
      * Prints the version number and the copyright notice.
@@ -332,6 +332,14 @@ public abstract class CtClass {
         return false;
     }
 
+    /**
+     * Returns <code>true</code> if this object represents a Kotlin class.
+     * @since 3.26
+     */
+    public boolean isKotlin() {
+        return hasAnnotation("kotlin.Metadata");
+    }
+
     /**
      * If this object represents an array, this method returns the component
      * type of the array.  Otherwise, it returns <code>null</code>.


=====================================
src/main/javassist/bytecode/ClassFileWriter.java
=====================================
@@ -700,6 +700,24 @@ public class ClassFileWriter {
             return num++;
         }
 
+        /**
+         * Adds a new <code>CONSTANT_Dynamic_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.26
+         */
+        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.


=====================================
src/main/javassist/bytecode/CodeIterator.java
=====================================
@@ -52,7 +52,7 @@ public class CodeIterator implements Opcode {
     protected byte[] bytecode;
     protected int endPos;
     protected int currentPos;
-    protected int mark;
+    protected int mark, mark2;
 
     protected CodeIterator(CodeAttribute ca) {
         codeAttr = ca;
@@ -64,7 +64,7 @@ public class CodeIterator implements Opcode {
      * Moves to the first instruction.
      */
     public void begin() {
-        currentPos = mark = 0;
+        currentPos = mark = mark2 = 0;
         endPos = getCodeLength();
     }
 
@@ -98,6 +98,20 @@ public class CodeIterator implements Opcode {
         mark = index;
     }
 
+    /**
+     * Sets a mark to the bytecode at the given index.
+     * The mark can be used to track the position of that bytecode
+     * when code blocks are inserted.
+     * If a code block is inclusively inserted at the position of the
+     * bytecode, the mark is set to the inserted code block.
+     *
+     * @see #getMark2()
+     * @since 3.26
+     */
+    public void setMark2(int index) {
+        mark2 = index;
+    }
+
     /**
      * Gets the index of the position of the mark set by
      * <code>setMark</code>.
@@ -108,6 +122,16 @@ public class CodeIterator implements Opcode {
      */
     public int getMark() { return mark; }
 
+    /**
+     * Gets the index of the position of the mark set by
+     * <code>setMark2</code>.
+     *
+     * @return the index of the position.
+     * @see #setMark2(int)
+     * @since 3.26
+     */
+    public int getMark2() { return mark2; }
+
     /**
      * Returns a Code attribute read with this iterator.
      */
@@ -646,6 +670,9 @@ public class CodeIterator implements Opcode {
 
             if (mark > pos || (mark == pos && exclusive))
                 mark += length2;
+
+            if (mark2 > pos || (mark2 == pos && exclusive))
+                mark2 += length2;
         }
 
         codeAttr.setCode(c);
@@ -1012,16 +1039,17 @@ public class CodeIterator implements Opcode {
 
     static class Pointers {
         int cursor;
-        int mark0, mark;
+        int mark0, mark, mark2;
         ExceptionTable etable;
         LineNumberAttribute line;
         LocalVariableAttribute vars, types;
         StackMapTable stack;
         StackMap stack2;
 
-        Pointers(int cur, int m, int m0, ExceptionTable et, CodeAttribute ca) {
+        Pointers(int cur, int m, int m2, int m0, ExceptionTable et, CodeAttribute ca) {
             cursor = cur;
             mark = m;
+            mark2 = m2;
             mark0 = m0;
             etable = et;    // non null
             line = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
@@ -1038,6 +1066,9 @@ public class CodeIterator implements Opcode {
             if (where < mark || (where == mark && exclusive))
                 mark += gapLength;
 
+            if (where < mark2 || (where == mark2 && exclusive))
+                mark2 += gapLength;
+
             if (where < mark0 || (where == mark0 && exclusive))
                 mark0 += gapLength;
 
@@ -1074,7 +1105,7 @@ public class CodeIterator implements Opcode {
                                   CodeAttribute ca, CodeAttribute.LdcEntry ldcs)
         throws BadBytecode
     {
-        Pointers pointers = new Pointers(0, 0, 0, etable, ca);
+        Pointers pointers = new Pointers(0, 0, 0, 0, etable, ca);
         List<Branch> jumps = makeJumpList(code, code.length, pointers);
         while (ldcs != null) {
             addLdcW(ldcs, jumps);
@@ -1118,11 +1149,12 @@ public class CodeIterator implements Opcode {
         if (gapLength <= 0)
             return code;
 
-        Pointers pointers = new Pointers(currentPos, mark, where, etable, ca);
+        Pointers pointers = new Pointers(currentPos, mark, mark2, where, etable, ca);
         List<Branch> jumps = makeJumpList(code, code.length, pointers);
         byte[] r = insertGap2w(code, where, gapLength, exclusive, jumps, pointers);
         currentPos = pointers.cursor;
         mark = pointers.mark;
+        mark2 = pointers.mark2;
         int where2 = pointers.mark0;
         if (where2 == currentPos && !exclusive)
             currentPos += gapLength;


=====================================
src/main/javassist/bytecode/ConstPool.java
=====================================
@@ -105,7 +105,12 @@ public final class ConstPool
     public static final int CONST_MethodType = MethodTypeInfo.tag;
 
     /**
-     * <code>CONSTANT_MethodHandle</code>
+     * <code>CONSTANT_Dynamic</code>
+     */
+    public static final int CONST_Dynamic = DynamicInfo.tag;
+
+    /**
+     * <code>CONSTANT_InvokeDynamic</code>
      */
     public static final int CONST_InvokeDynamic = InvokeDynamicInfo.tag;
 
@@ -748,7 +753,7 @@ public final class ConstPool
      * indirectly specified by the given index.
      *
      * @param index     an index to a <code>CONSTANT_InvokeDynamic_info</code>.
-     * @return  the descriptor of the method.
+     * @return  the descriptor of the bootstrap method.
      * @since 3.17
      */
     public String getInvokeDynamicType(int index)
@@ -762,6 +767,52 @@ public final class ConstPool
         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.26
+     */
+    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.26
+     */
+    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 bootstrap method.
+     * @since 3.26
+     */
+    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.
@@ -1195,6 +1246,18 @@ public final class ConstPool
         return addItem(new InvokeDynamicInfo(bootstrap, nameAndType, numOfItems));
     }
 
+    /**
+     * Adds a new <code>CONSTANT_Dynamic_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.26
+     */
+    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.
@@ -1342,6 +1405,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 +2388,63 @@ 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;


=====================================
src/main/javassist/compiler/MemberCodeGen.java
=====================================
@@ -619,6 +619,18 @@ public class MemberCodeGen extends CodeGen {
                           aload0pos, found);
     }
 
+    private boolean isFromSameDeclaringClass(CtClass outer, CtClass inner) {
+        try {
+            while (outer != null) {
+                if (isEnclosing(outer, inner))
+                    return true;
+                outer = outer.getDeclaringClass();
+            }
+        }
+        catch (NotFoundException e) {}
+        return false;
+    }
+
     private void atMethodCallCore2(CtClass targetClass, String mname,
                                    boolean isStatic, boolean isSpecial,
                                    int aload0pos,
@@ -636,19 +648,8 @@ public class MemberCodeGen extends CodeGen {
                 throw new CompileError("no such constructor: " + targetClass.getName());
 
             if (declClass != thisClass && AccessFlag.isPrivate(acc)) {
-                boolean isNested = false;
-                if (declClass.getClassFile().getMajorVersion() >= ClassFile.JAVA_11) {
-                    try {
-                        CtClass[] nestedClasses = declClass.getNestedClasses();
-                        for (int i = 0; i < nestedClasses.length; i++) {
-                            if (thisClass == nestedClasses[i]) {
-                                isNested = true;
-                                break;
-                            }
-                        }
-                    } catch (NotFoundException ignored) { }
-                }
-                if (!isNested) {
+                if (declClass.getClassFile().getMajorVersion() < ClassFile.JAVA_11
+                        || !isFromSameDeclaringClass(declClass, thisClass)) {
                     desc = getAccessibleConstructor(desc, declClass, minfo);
                     bytecode.addOpcode(Opcode.ACONST_NULL); // the last parameter
                 }


=====================================
src/main/javassist/compiler/MemberResolver.java
=====================================
@@ -539,7 +539,7 @@ public class MemberResolver implements TokenId {
                 if (intfs[i].getName().equals(interfaceName))
                     return intfs[i];
         } catch (NotFoundException e) {}
-        throw new CompileError("cannot find the super inetrface " + interfaceName
+        throw new CompileError("cannot find the super interface " + interfaceName
                                + " of " + c.getName());
     }
 


=====================================
src/main/javassist/util/proxy/ProxyFactory.java
=====================================
@@ -49,6 +49,7 @@ import javassist.bytecode.ExceptionsAttribute;
 import javassist.bytecode.FieldInfo;
 import javassist.bytecode.MethodInfo;
 import javassist.bytecode.Opcode;
+import javassist.bytecode.SignatureAttribute;
 import javassist.bytecode.StackMapTable;
 
 /*
@@ -186,6 +187,8 @@ public class ProxyFactory {
     private String basename;
     private String superName;
     private Class<?> thisClass;
+    private String genericSignature;
+
     /**
      * per factory setting initialised from current setting for useCache but able to be reset before each create call
      */
@@ -389,6 +392,7 @@ public class ProxyFactory {
         signatureMethods = null;
         hasGetHandler = false;
         thisClass = null;
+        genericSignature = null;
         writeDirectory = null;
         factoryUseCache = useCache;
         factoryWriteReplace = useWriteReplace;
@@ -435,6 +439,34 @@ public class ProxyFactory {
         signature = null;
     }
 
+    /**
+     * Sets the generic signature for the proxy class.
+     * <p>For example,
+     *
+     * <pre>class NullPtr<T> {
+     *     T get() { return null; }
+     * }
+     * </pre>
+     *
+     * <p>The following code makes a proxy for <code>NullPtr<String></code>:
+     *
+     * <pre>ProxyFactory factory = new ProxyFactory();
+     * factory.setSuperclass(NullPtr.class);
+     * factory.setGenericSignature("LNullPtr<Ljava/lang/String;>;");
+     * NullPtr<?> np = (NullPtr<?>)factory.create(null, null);
+     *java.lang.reflect.Type[] x = ((java.lang.reflect.ParameterizedType)np.getClass().getGenericSuperclass())
+     *                                                                     .getActualTypeArguments();
+     * // x[0] == String.class
+     * </pre>
+     * 
+     * @param sig   a generic signature.
+     * @see javassist.CtClass#setGenericSignature(String)
+     * @since 3.26
+     */
+    public void setGenericSignature(String sig) {
+        genericSignature = sig;
+    }
+
     /**
      * Generates a proxy class using the current filter.
      * The module or package where a proxy class is created
@@ -885,6 +917,11 @@ public class ProxyFactory {
         finfo4.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC| AccessFlag.FINAL);
         cf.addField(finfo4);
 
+        if (genericSignature != null) {
+            SignatureAttribute sa = new SignatureAttribute(pool, genericSignature);
+            cf.addAttribute(sa);
+        }
+
         // HashMap allMethods = getMethods(superClass, interfaces);
         // int size = allMethods.size();
         makeConstructors(classname, cf, pool, classname);


=====================================
src/test/Test.java
=====================================
@@ -44,9 +44,11 @@ public class Test {
 
         final CtClass ctClass = classPool.get(INVALID_STACK_MAP_FRAME);
         final CtMethod method = ctClass.getDeclaredMethod("bytecodeVerifyError");
-        method.addLocalVariable("test_localVariable", CtClass.intType);
-        method.insertBefore("{ test_localVariable = 1; }");
-        ctClass.debugWriteFile();
+        // method.addLocalVariable("test_localVariable", CtClass.intType);
+        method.insertBefore("{ java.math.BigDecimal d = null; d.divide(d); }");
+        //ctClass.debugWriteFile();
+        System.out.println("ok");
+        ctClass.writeFile();
         Class<?> cc = ctClass.toClass();
         System.out.println(cc.getName());
         InvalidStackMapFrame obj = (InvalidStackMapFrame)cc.getDeclaredConstructor().newInstance();


=====================================
src/test/javassist/JvstTest5.java
=====================================
@@ -490,6 +490,33 @@ public class JvstTest5 extends JvstTestRoot {
         }
     }
 
+    public void testNestPrivateConstructor2() throws Exception {
+        CtClass cc = sloader.get("test5.NestHost4$InnerClass1");
+        cc.instrument(new ExprEditor() {
+            public void edit(NewExpr e) throws CannotCompileException {
+                String code = "$_ = $proceed($$);";
+                e.replace(code);
+            }
+        });
+        cc.writeFile();
+
+        cc = sloader.get("test5.NestHost4$InnerClass1$InnerClass5");
+        cc.instrument(new ExprEditor() {
+            public void edit(NewExpr e) throws CannotCompileException {
+                String code = "$_ = $proceed($$);";
+                e.replace(code);
+            }
+        });
+        cc.writeFile();
+        try {
+            Class<?> nestHost4Class = cloader.loadClass("test5.NestHost4");
+            nestHost4Class.getDeclaredConstructor().newInstance();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            fail("it should be able to access the private constructor of the nest host");
+        }
+    }
+
     public void testSwitchCaseWithStringConstant2() throws Exception {
         CtClass cc = sloader.makeClass("test5.SwitchCase2");
         cc.addMethod(CtNewMethod.make(
@@ -519,4 +546,16 @@ public class JvstTest5 extends JvstTestRoot {
         Object obj = make(cc.getName());
         assertEquals(1, invoke(obj, "run"));
     }
+
+    // Issue #275
+    public void testRedundantInsertAfter() throws Exception {
+        CtClass cc = sloader.get(test5.InsertAfter.class.getName());
+        CtMethod m = cc.getDeclaredMethod("foo");
+        m.insertAfter("{ $_ += 1; }", false, true);
+        CtMethod m2 = cc.getDeclaredMethod("bar");
+        m2.insertAfter("{ $_ += 1; }", true, true);
+        cc.writeFile();
+        Object obj = make(cc.getName());
+        assertEquals(71 + 22, invoke(obj, "run"));
+    }
 }


=====================================
src/test/javassist/proxyfactory/GenSig.java
=====================================
@@ -0,0 +1,4 @@
+package javassist.proxyfactory;
+
+class GenSig<T> {
+}


=====================================
src/test/javassist/proxyfactory/ProxyFactoryTest.java
=====================================
@@ -152,4 +152,15 @@ public class ProxyFactoryTest extends TestCase {
             }
         });
     }
+
+    // Issue #263
+    public void testGenericSignature() throws Exception {
+        ProxyFactory factory = new ProxyFactory();
+        factory.setSuperclass(GenSig.class);
+        factory.setGenericSignature("Ljavassist/proxyfactory/GenSig<Ljava/lang/Integer;>;");
+        GenSig gs = (GenSig)factory.create(null, null);
+        java.lang.reflect.Type[] x = ((java.lang.reflect.ParameterizedType)gs.getClass().getGenericSuperclass())
+                                                                             .getActualTypeArguments();
+        assertEquals(Integer.class, x[0]);
+    }
 }


=====================================
src/test/test5/InsertAfter.java
=====================================
@@ -0,0 +1,35 @@
+package test5;
+
+public class InsertAfter {
+    public int run() {
+        return foo(7) + bar(20);
+    }
+
+    public int foo(int k) {
+        if (k > 0)
+            if (k > 10)
+                return k + 1;
+            else
+                return k * 10;
+        else
+            return k * 100;
+    }
+
+    public int bar(int k) {
+        if (k > 0)
+            try {
+                if (k > 10)
+                    return k + 1;
+                else
+                    return k * 10;
+            }
+            catch (Exception e) {
+                if (k > 0)
+                    return k * 1000;
+                else
+                    throw e;
+            }
+        else
+            return k * 100;
+    }
+}


=====================================
src/test/test5/NestHost4.java
=====================================
@@ -0,0 +1,26 @@
+package test5;
+
+public class NestHost4 {
+  public void test() {
+    new InnerClass1().new InnerClass5();
+  }
+
+  private class InnerClass1 {
+    private InnerClass1() {
+      new InnerClass2();
+    }
+
+    private class InnerClass5 {
+      private InnerClass5() {
+        new InnerClass2().new InnerClass3();
+      }
+    }
+  }
+
+  private class InnerClass2 {
+
+    private class InnerClass3 {
+
+    }
+  }
+}



View it on GitLab: https://salsa.debian.org/java-team/javassist/commit/1b81f14653d5044a63b02061cbac40d95993a81a

-- 
View it on GitLab: https://salsa.debian.org/java-team/javassist/commit/1b81f14653d5044a63b02061cbac40d95993a81a
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20200127/07c14f3d/attachment.html>


More information about the pkg-java-commits mailing list