Browse Source

fiexed JASSIST-238

tags/rel_3_19_0_ga
chibash 9 years ago
parent
commit
f2093c28be

+ 2
- 1
Readme.html View File



<p>-version 3.19 <p>-version 3.19
<ul> <ul>
<li>JIRA JASSIST-158, 205, 206, 207, 208, 209, 211, 212, 216, 220, 223, 224, 227, 230, 234, 235, 236.
<li>JIRA JASSIST-158, 205, 206, 207, 208, 209, 211, 212, 216, 220, 223, 224,
227, 230, 234, 235, 236, 237.
</ul> </ul>
</p> </p>



BIN
javassist.jar View File


+ 32
- 5
src/main/javassist/bytecode/Bytecode.java View File

* @see Descriptor#ofConstructor(CtClass[]) * @see Descriptor#ofConstructor(CtClass[])
*/ */
public void addInvokespecial(CtClass clazz, String name, String desc) { public void addInvokespecial(CtClass clazz, String name, String desc) {
addInvokespecial(constPool.addClassInfo(clazz), name, desc);
boolean isInterface = clazz == null ? false : clazz.isInterface();
addInvokespecial(isInterface,
constPool.addClassInfo(clazz), name, desc);
} }


/** /**
* Appends INVOKESPECIAL.
* Appends INVOKESPECIAL. The invoked method must not be a default
* method declared in an interface.
* *
* @param clazz the fully-qualified class name. * @param clazz the fully-qualified class name.
* @param name the method name * @param name the method name
* @see Descriptor#ofConstructor(CtClass[]) * @see Descriptor#ofConstructor(CtClass[])
*/ */
public void addInvokespecial(String clazz, String name, String desc) { public void addInvokespecial(String clazz, String name, String desc) {
addInvokespecial(constPool.addClassInfo(clazz), name, desc);
addInvokespecial(false, constPool.addClassInfo(clazz), name, desc);
} }


/** /**
* Appends INVOKESPECIAL.
* Appends INVOKESPECIAL. The invoked method must not be a default
* method declared in an interface.
* *
* @param clazz the index of <code>CONSTANT_Class_info</code> * @param clazz the index of <code>CONSTANT_Class_info</code>
* structure. * structure.
* @see Descriptor#ofConstructor(CtClass[]) * @see Descriptor#ofConstructor(CtClass[])
*/ */
public void addInvokespecial(int clazz, String name, String desc) { public void addInvokespecial(int clazz, String name, String desc) {
addInvokespecial(false, clazz, name, desc);
}

/**
* Appends INVOKESPECIAL.
*
* @param isInterface true if the invoked method is a default method
* declared in an interface.
* @param clazz the index of <code>CONSTANT_Class_info</code>
* structure.
* @param name the method name
* @param desc the descriptor of the method signature.
*
* @see Descriptor#ofMethod(CtClass,CtClass[])
* @see Descriptor#ofConstructor(CtClass[])
*/
public void addInvokespecial(boolean isInterface, int clazz, String name, String desc) {
add(INVOKESPECIAL); add(INVOKESPECIAL);
addIndex(constPool.addMethodrefInfo(clazz, name, desc));
int index;
if (isInterface)
index = constPool.addInterfaceMethodrefInfo(clazz, name, desc);
else
index = constPool.addMethodrefInfo(clazz, name, desc);

addIndex(index);
growStack(Descriptor.dataSize(desc) - 1); growStack(Descriptor.dataSize(desc) - 1);
} }



+ 36
- 22
src/main/javassist/compiler/MemberCodeGen.java View File

} }
else if (op == '.') { else if (op == '.') {
ASTree target = e.oprand1(); ASTree target = e.oprand1();
if (target instanceof Keyword)
if (((Keyword)target).get() == SUPER)
isSpecial = true;

try {
target.accept(this);
String classFollowedByDotSuper = TypeChecker.isDotSuper(target);
if (classFollowedByDotSuper != null) {
isSpecial = true;
targetClass = MemberResolver.getSuperInterface(thisClass,
classFollowedByDotSuper);
if (inStaticMethod || (cached != null && cached.isStatic()))
isStatic = true; // should be static
else {
aload0pos = bytecode.currentPc();
bytecode.addAload(0); // this
}
} }
catch (NoFieldException nfe) {
if (nfe.getExpr() != target)
throw nfe;

// it should be a static method.
exprType = CLASS;
arrayDim = 0;
className = nfe.getField(); // JVM-internal
isStatic = true;
else {
if (target instanceof Keyword)
if (((Keyword)target).get() == SUPER)
isSpecial = true;

try {
target.accept(this);
}
catch (NoFieldException nfe) {
if (nfe.getExpr() != target)
throw nfe;

// it should be a static method.
exprType = CLASS;
arrayDim = 0;
className = nfe.getField(); // JVM-internal
isStatic = true;
}

if (arrayDim > 0)
targetClass = resolver.lookupClass(javaLangObject, true);
else if (exprType == CLASS /* && arrayDim == 0 */)
targetClass = resolver.lookupClassByJvmName(className);
else
badMethod();
} }

if (arrayDim > 0)
targetClass = resolver.lookupClass(javaLangObject, true);
else if (exprType == CLASS /* && arrayDim == 0 */)
targetClass = resolver.lookupClassByJvmName(className);
else
badMethod();
} }
else else
badMethod(); badMethod();

+ 14
- 0
src/main/javassist/compiler/MemberResolver.java View File

import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.List; import java.util.List;
import java.util.Iterator; import java.util.Iterator;

import javassist.*; import javassist.*;
import javassist.bytecode.*; import javassist.bytecode.*;
import javassist.compiler.ast.*; import javassist.compiler.ast.*;
+ c.getName()); + c.getName());
} }


public static CtClass getSuperInterface(CtClass c, String interfaceName)
throws CompileError
{
try {
CtClass[] intfs = c.getInterfaces();
for (int i = 0; i < intfs.length; i++)
if (intfs[i].getName().equals(interfaceName))
return intfs[i];
} catch (NotFoundException e) {}
throw new CompileError("cannot find the super inetrface " + interfaceName
+ " of " + c.getName());
}

public static String javaToJvmName(String classname) { public static String javaToJvmName(String classname) {
return classname.replace('.', '/'); return classname.replace('.', '/');
} }

+ 4
- 2
src/main/javassist/compiler/Parser.java View File

* | postfix.expr "." Identifier * | postfix.expr "." Identifier
* | postfix.expr ( "[" "]" )* "." CLASS * | postfix.expr ( "[" "]" )* "." CLASS
* | postfix.expr "#" Identifier * | postfix.expr "#" Identifier
* | postfix.expr "." SUPER
* *
* "#" is not an operator of regular Java. It separates * "#" is not an operator of regular Java. It separates
* a class name and a member name in an expression for static member * a class name and a member name in an expression for static member
case '.' : case '.' :
lex.get(); lex.get();
t = lex.get(); t = lex.get();
if (t == CLASS) {
if (t == CLASS)
expr = parseDotClass(expr, 0); expr = parseDotClass(expr, 0);
}
else if (t == SUPER)
expr = Expr.make('.', new Symbol(toClassName(expr)), new Keyword(t));
else if (t == Identifier) { else if (t == Identifier) {
str = lex.getString(); str = lex.getString();
expr = Expr.make('.', expr, new Member(str)); expr = Expr.make('.', expr, new Member(str));

+ 47
- 21
src/main/javassist/compiler/TypeChecker.java View File

false); false);
else if (op == '.') { else if (op == '.') {
ASTree target = e.oprand1(); ASTree target = e.oprand1();
try {
target.accept(this);
}
catch (NoFieldException nfe) {
if (nfe.getExpr() != target)
throw nfe;

// it should be a static method.
exprType = CLASS;
arrayDim = 0;
className = nfe.getField(); // JVM-internal
e.setOperator(MEMBER);
e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(
className)));
String classFollowedByDotSuper = isDotSuper(target);
if (classFollowedByDotSuper != null)
targetClass = MemberResolver.getSuperInterface(thisClass,
classFollowedByDotSuper);
else {
try {
target.accept(this);
}
catch (NoFieldException nfe) {
if (nfe.getExpr() != target)
throw nfe;

// it should be a static method.
exprType = CLASS;
arrayDim = 0;
className = nfe.getField(); // JVM-internal
e.setOperator(MEMBER);
e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(
className)));
}

if (arrayDim > 0)
targetClass = resolver.lookupClass(javaLangObject, true);
else if (exprType == CLASS /* && arrayDim == 0 */)
targetClass = resolver.lookupClassByJvmName(className);
else
badMethod();
} }

if (arrayDim > 0)
targetClass = resolver.lookupClass(javaLangObject, true);
else if (exprType == CLASS /* && arrayDim == 0 */)
targetClass = resolver.lookupClassByJvmName(className);
else
badMethod();
} }
else else
badMethod(); badMethod();
throw new CompileError("bad method"); throw new CompileError("bad method");
} }


/**
* Returns non-null if target is something like Foo.super
* for accessing the default method in an interface.
* Otherwise, null.
*
* @return the class name followed by {@code .super} or null.
*/
static String isDotSuper(ASTree target) {
if (target instanceof Expr) {
Expr e = (Expr)target;
if (e.getOperator() == '.') {
ASTree right = e.oprand2();
if (right instanceof Keyword && ((Keyword)right).get() == SUPER)
return ((Symbol)e.oprand1()).get();
}
}

return null;
}

/** /**
* @return a pair of the class declaring the invoked method * @return a pair of the class declaring the invoked method
* and the MethodInfo of that method. Never null. * and the MethodInfo of that method. Never null.

+ 4
- 21
src/test/Test.java View File



public class Test { public class Test {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
if (args.length > 1) {
new Test().bar(3);
return;
}

ClassPool cp = ClassPool.getDefault(); ClassPool cp = ClassPool.getDefault();
CtClass inner3 = cp.get("test2.Anon$Anon2.1");
CtBehavior ct = inner3.getEnclosingBehavior();
/* CtClass str = cp.get("java.lang.String");
CtClass cc = cp.get("Test");
cc.getClassFile().setMajorVersion(javassist.bytecode.ClassFile.JAVA_4);
CtMethod m = cc.getDeclaredMethod("bar");
m.addLocalVariable("aVar", str);
m.insertAfter(" dismiss( aVar );" , true);
cc.getClassFile().setMajorVersion(javassist.bytecode.ClassFile.JAVA_7);
m.insertBefore("aVar = initVar();");
cc.writeFile();*/
CtClass cc = cp.get("test5.DefaultMethod");
CtMethod m = CtNewMethod.make("public int run(){ return test5.DefaultMethodIntf.super.foo(); }", cc);
cc.addMethod(m);
cc.writeFile();
} }

public void bar(int i) { foo(i); }
public void foo(int i) { System.out.println(i); }
public String initVar() { return "init"; }
public void dismiss(String s) { System.out.println(s); }
} }

+ 1
- 0
src/test/javassist/JvstTest.java View File

suite.addTestSuite(JvstTest2.class); suite.addTestSuite(JvstTest2.class);
suite.addTestSuite(JvstTest3.class); suite.addTestSuite(JvstTest3.class);
suite.addTestSuite(JvstTest4.class); suite.addTestSuite(JvstTest4.class);
suite.addTestSuite(JvstTest5.class);
suite.addTestSuite(LoaderTestByRandall.class); suite.addTestSuite(LoaderTestByRandall.class);
suite.addTestSuite(javassist.bytecode.BytecodeTest.class); suite.addTestSuite(javassist.bytecode.BytecodeTest.class);
suite.addTestSuite(javassist.bytecode.StackMapTest.class); suite.addTestSuite(javassist.bytecode.StackMapTest.class);

+ 3
- 3
src/test/javassist/JvstTest4.java View File

import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;


import javassist.bytecode.*; import javassist.bytecode.*;
import javassist.bytecode.annotation.Annotation; import javassist.bytecode.annotation.Annotation;
long t2 = endTime2 - endTime; long t2 = endTime2 - endTime;
long t3 = endTime3 - endTime2; long t3 = endTime3 - endTime2;
System.out.println("JIRA150: " + t1 + ", " + t2 + ", " + t3); System.out.println("JIRA150: " + t1 + ", " + t2 + ", " + t3);
assertTrue(t2 < t1 * 5);
assertTrue(t3 < t1 * 3);
assertTrue("performance test (the next try may succeed): " + t1 + "/ 5 < " + t2,
t2 < t1 * 5);
assertTrue("", t3 < t1 * 3);
} }


public void testJIRA150b() throws Exception { public void testJIRA150b() throws Exception {

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

package javassist;

public class JvstTest5 extends JvstTestRoot {
public JvstTest5(String name) {
super(name);
}

public void testDollarClassInStaticMethod() throws Exception {
CtClass cc = sloader.makeClass("test5.DollarClass");
CtMethod m = CtNewMethod.make("public static int run(){ return $class.getName().length(); }", cc);
cc.addMethod(m);
m = CtNewMethod.make("public int run2(){ return $class.getName().length(); }", cc);
cc.addMethod(m);
cc.writeFile();
Object obj = make(cc.getName());
assertEquals(cc.getName().length(), invoke(obj, "run"));
assertEquals(cc.getName().length(), invoke(obj, "run2"));
}

public void testSuperDefaultMethodCall() throws Exception {
CtClass cc = sloader.get("test5.DefaultMethod");
CtMethod m = CtNewMethod.make("public int run(){ return test5.DefaultMethodIntf.super.foo(); }", cc);
cc.addMethod(m);
m = CtNewMethod.make("public int run2(){ return test5.DefaultMethodIntf.baz(); }", cc);
cc.addMethod(m);
m = CtNewMethod.make("public int run3(){ return test5.DefaultMethodIntf.super.baz(); }", cc);
cc.addMethod(m);
cc.writeFile();
Object obj = make(cc.getName());
assertEquals(1, invoke(obj, "run"));
assertEquals(10, invoke(obj, "run2"));
assertEquals(10, invoke(obj, "run3"));
}
}

+ 19
- 0
src/test/test5/DefaultMethod.java View File

package test5;

interface DefaultMethodSupIntf {
default int foo() { return 0; }
}

interface DefaultMethodIntf extends DefaultMethodSupIntf {
default int foo() { return 1; }
static int baz() { return 10; }
}

public class DefaultMethod implements DefaultMethodIntf {
public int bar() { return DefaultMethodIntf.super.foo(); }

public static void main(String[] args) {
int i = new DefaultMethod().bar() + new DefaultMethod().foo() + DefaultMethodIntf.baz();
System.out.println(i);
}
}

Loading…
Cancel
Save