[Git][java-team/javassist][master] 4 commits: New upstream version 3.26.0
Emmanuel Bourg
gitlab at salsa.debian.org
Mon Jan 27 09:17:40 GMT 2020
Emmanuel Bourg pushed to branch master at Debian Java Maintainers / javassist
Commits:
1b81f146 by Emmanuel Bourg at 2020-01-27T10:14:16+01:00
New upstream version 3.26.0
- - - - -
6a3df685 by Emmanuel Bourg at 2020-01-27T10:14:20+01:00
Update upstream source from tag 'upstream/3.26.0'
Update to upstream version '3.26.0'
with Debian dir 17da75c1cae68fb4ceb53621ac935f825ffe7d09
- - - - -
3193e001 by Emmanuel Bourg at 2020-01-27T10:17:00+01:00
Standards-Version updated to 4.5.0
- - - - -
a7ab003b by Emmanuel Bourg at 2020-01-27T10:17:13+01:00
Upload to unstable
- - - - -
22 changed files:
- Readme.html
- build.xml
- debian/changelog
- debian/control
- 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="**">
=====================================
debian/changelog
=====================================
@@ -1,3 +1,11 @@
+javassist (1:3.26.0-1) unstable; urgency=medium
+
+ * Team upload.
+ * New upstream release
+ * Standards-Version updated to 4.5.0
+
+ -- Emmanuel Bourg <ebourg at apache.org> Mon, 27 Jan 2020 10:17:05 +0100
+
javassist (1:3.25.0-1) unstable; urgency=medium
* Team upload.
=====================================
debian/control
=====================================
@@ -12,7 +12,7 @@ Build-Depends:
libmaven-bundle-plugin-java,
libmaven-javadoc-plugin-java,
maven-debian-helper (>= 2.1)
-Standards-Version: 4.4.0
+Standards-Version: 4.5.0
Vcs-Git: https://salsa.debian.org/java-team/javassist.git
Vcs-Browser: https://salsa.debian.org/java-team/javassist
Homepage: http://jboss-javassist.github.io/javassist/
=====================================
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/compare/5ade7770005e76c832f42d30329e56966e91a4ab...a7ab003b405b41fa17c03da38348118cb917bfee
--
View it on GitLab: https://salsa.debian.org/java-team/javassist/compare/5ade7770005e76c832f42d30329e56966e91a4ab...a7ab003b405b41fa17c03da38348118cb917bfee
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/6fdf272d/attachment.html>
More information about the pkg-java-commits
mailing list