Browse Source

Merge 072772373e into 700be6f6f9

pull/452/merge
Adahel 1 year ago
parent
commit
fee6ab3655
No account linked to committer's email address

+ 1
- 1
build.xml View File

@@ -6,7 +6,7 @@

<project name="javassist" default="jar" basedir=".">

<property name="dist-version" value="javassist-3.29.2-GA"/>
<property name="dist-version" value="javassist-3.30.0-GA-SNAPSHOT"/>

<property environment="env"/>
<property name="target.jar" value="javassist.jar"/>

+ 1
- 1
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.29.2-GA</version>
<version>3.30.0-GA-SNAPSHOT</version>
<name>Javassist</name>
<url>http://www.javassist.org/</url>


+ 79
- 0
src/main/javassist/CtBehavior.java View File

@@ -20,6 +20,7 @@ import javassist.bytecode.AccessFlag;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.AttributeInfo;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.ByteArray;
import javassist.bytecode.Bytecode;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.CodeIterator;
@@ -1309,4 +1310,82 @@ public abstract class CtBehavior extends CtMember {
throw new CannotCompileException(e);
}
}

/**
* Inserts bytecode after the local variable specified by the type and position
* in the body.
*
* @param type the type of the variable.
* @param pos the position of the local variable with the same type. The
* bytecode is inserted at the beginning of the code after the
* local variable specified by the type and this position.
* @param addName add or change the local variable name. If the value of addName
* is null it does nothing.
* @param src the source code representing the inserted bytecode. It must be
* a single statement or block.
* @since 3.30
*/
public void insertAfterLocalVariable(CtClass type, int pos, String addName, String src)
throws CannotCompileException {
ConstPool cp = methodInfo.getConstPool();
CodeAttribute ca = methodInfo.getCodeAttribute();
if (ca == null)
throw new CannotCompileException("no method body");

LocalVariableAttribute va = (LocalVariableAttribute) ca.getAttribute(LocalVariableAttribute.tag);
if (va == null)
throw new CannotCompileException("no local variable");

CtClass cc = declaringClass;
cc.checkModify();
String desc = Descriptor.of(type);
int i = 0;
for (int j : va.entryListOrderedByIndex()) {
if (va.descriptor(j).equals(desc)) {
if (i != pos) {
i++;
continue;
}

if (addName != null) {
ByteArray.write16bit(cp.addUtf8Info(addName), va.get(), j * 10 + 6);
}

int index = va.startPc(j);
CodeIterator iterator = ca.iterator();
Javac jv = new Javac(cc);
try {
jv.recordLocalVariables(ca, index);
jv.recordParams(getParameterTypes(), Modifier.isStatic(getModifiers()));
jv.setMaxLocals(ca.getMaxLocals());
jv.compileStmnt(src);
Bytecode b = jv.getBytecode();
int locals = b.getMaxLocals();
int stack = b.getMaxStack();
ca.setMaxLocals(locals);

/*
* We assume that there is no values in the operand stack at the position where
* the bytecode is inserted.
*/
if (stack > ca.getMaxStack())
ca.setMaxStack(stack);

index = iterator.insertAt(index, b.get());
iterator.insert(b.getExceptionTable(), index);
methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
return;
} catch (NotFoundException e) {
throw new CannotCompileException(e);
} catch (CompileError e) {
throw new CannotCompileException(e);
} catch (BadBytecode e) {
throw new CannotCompileException(e);
}
}
}

throw new CannotCompileException(
String.format("no local variable with this type %s and position %s", new Object[] { type, pos }));
}
}

+ 1
- 1
src/main/javassist/CtClass.java View File

@@ -69,7 +69,7 @@ public abstract class CtClass {
/**
* The version number of this release.
*/
public static final String version = "3.29.2-GA";
public static final String version = "3.30.0-GA-SNAPSHOT";

/**
* Prints the version number and the copyright notice.

+ 30
- 0
src/main/javassist/bytecode/LocalVariableAttribute.java View File

@@ -18,6 +18,9 @@ package javassist.bytecode;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
@@ -351,4 +354,31 @@ public class LocalVariableAttribute extends AttributeInfo {
LocalVariableAttribute makeThisAttr(ConstPool cp, byte[] dest) {
return new LocalVariableAttribute(cp, tag, dest);
}

/**
* Undocumented method. Do not use; internal-use only.
*
* Returns a list of entries in the correct order according to the local
* variable index. This method is for internal use only as the order may be
* wrong with local variables with different type descriptor.
*
* @see #index(int)
* @since 3.30
*/
public List<Integer> entryListOrderedByIndex() {
int n = tableLength();
Integer[] entries = new Integer[n];
for (int i = 0; i < n; i++) {
int index = index(i);
while (index < n && entries[index] != null) {
index++;
}

if (index < n) {
entries[index] = i;
}
}

return Collections.unmodifiableList(Arrays.asList(entries));
}
}

+ 23
- 0
src/test/javassist/JvstTest5.java View File

@@ -593,4 +593,27 @@ public class JvstTest5 extends JvstTestRoot {
}
catch (CannotCompileException e) {}
}

// Issue #430
public void testInsertAfterLocalVariable() throws Exception {
CtClass cc = sloader.get("test5.InsertLocalVariable");
CtMethod m1 = cc.getDeclaredMethod("foo");
m1.insertAfterLocalVariable(CtClass.intType, 0, null, "$1++;");
m1.insertAfterLocalVariable(CtClass.intType, 1, null, "$2++;");
m1.insertAfterLocalVariable(CtClass.intType, 2, null, "$3++;");
m1.insertAfterLocalVariable(CtClass.booleanType, 0, null, "bI = true;");
m1.insertAfterLocalVariable(CtClass.intType, 3, "iL", "iL++;");
m1.insertAfterLocalVariable(CtClass.booleanType, 1, null, "bJ = false;");
m1.insertAfterLocalVariable(CtClass.intType, 4, "iM", "iM++;");
m1.insertAfterLocalVariable(CtClass.intType, 5, "iN", "iN++;");
m1.insertAfterLocalVariable(CtClass.booleanType, 2, null, "bK = true;");
m1.insertAfterLocalVariable(CtClass.intType, 6, "iO", "iO++;");
m1.insertAfterLocalVariable(CtClass.intType, 7, "iP", "iP++;");
m1.insertAfterLocalVariable(CtClass.intType, 8, "iQ", "iQ++;");
m1.insertAfterLocalVariable(CtClass.intType, 9, "iR", "iR++;");
m1.insertAfterLocalVariable(CtClass.intType, 10, "iS", "iS++;");
cc.writeFile();
Object obj = make(cc.getName());
assertEquals(12, invoke(obj, "test"));
}
}

+ 67
- 0
src/test/test5/InsertLocalVariable.java View File

@@ -0,0 +1,67 @@
package test5;

public class InsertLocalVariable {
int k;

public InsertLocalVariable() {
k = 1;
}

public int test() {
foo(0, 0, 0);
return k;
}

public void foo(int i /* 0 */, int j /* 1 */, int k /* 2 */) {
boolean bI = false; /* 0 */
int l = 0; /* 3 */
if (l == 0) {
this.k = -1;
return;
}

try {
boolean bJ = true; /* 1 */
if (!bJ) {
throw new Exception();
}
} catch (Exception e /* 0 */) {
int m = 0; /* 4 */
l += m;
if (bI) {
int n = 0; /* 5 */
l += n;
}

for (boolean bK = false /* 2 */; l == 3;) {
if (bK) {
int o = 0; /* 6 */
l += o;
}
}

while (l == 4) {
int p = 0; /* 7 */
l += p;
}

do {
int q = 0; /* 8 */
l += q;
} while (false);

switch (l) {
case 6:
int r = 0; /* 9 */
l += r;
}
}

int s = 0; /* 10 */
this.k += i;
this.k += j;
this.k += k;
this.k += l;
this.k += s;
}
}

Loading…
Cancel
Save