Yes, I agree with Ondrej. Take a look at the example I have attached to this message. There are four classes A,B,C and Test as in your example, I wrote a little Java program, compiled it to class files, then produced Jimple using Soot, edited the Jimple to put the private in class B and changed the signature of the virtualinvoke in class Test (see below) and then used Soot to produce class files from the Jimple. I also decompiled the new class files (files in dava/src). This gives you a source code look at what I have. Note that the decompiled source will not recompile because of the private f in class B. However, you can run the class file Test. Try, java -verify Test and it will say that it is running the method in class A. Here is the jimple for Test.java, /***************************************** public class Test extends java.lang.Object { public void <init>() { Test r0; r0 := @this: Test; specialinvoke r0.<java.lang.Object: void <init>()>(); return; } public static void main(java.lang.String[] ) { java.lang.String[] r0; C $r1, r2; r0 := @parameter0: java.lang.String[]; $r1 = new C; specialinvoke $r1.<C: void <init>()>(); r2 = $r1; virtualinvoke r2.<A: void f()>(); <--------------- return; } } ******************************************* Look at the statement marked by the arrow. This must use the signature A in the call to f. If either B or C is used, then the bytecode fails when run with the verifier (and it writes out that it is running f in B if you turn the verifier off). Cheers, Laurie +-------------------------------------------------------------+ | Laurie Hendren, Professor, School of Computer Science | | McGill University | | 318 McConnell Engineering Building tel: (514) 398-7391 | | 3480 University Street fax: (514) 398-3883 | | Montreal, Quebec H3A 2A7 hendren@cs.mcgill.ca | | CANADA http://www.sable.mcgill.ca/~hendren | +-------------------------------------------------------------+ On Thu, 6 Mar 2003, Ondrej LHOTAK wrote: > The lookup code implemented in Soot follows the description given in the > Java Virtual Machine Specification, under invokevirtual: > http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc6.html#invokevirtual > > According to this description, for the example you gave, the A.f() that > Soot returns would indeed be the correct method to invoke. Contrary to > your claim, it is *not* true that C cannot access any f(), neither from > A nor B. > > If you still think I have misunderstood the specification, please let me > know. > > Ondrej > > On Thu, Mar 06, 2003 at 11:17:21AM -0500, Weilei Zhang wrote: > > The following is from the method resolveConcreteDispatch in Hierarchy.java. > > public SootMethod resolveConcreteDispatch(SootClass concreteType, SootMethod m) > > { > > .......... > > while (it.hasNext()) > > { > > SootClass c = (SootClass)it.next(); > > if (c.declaresMethod(methodSig) > > && isVisible( c, m ) > > ) { > > return c.getMethod(methodSig); > > } > > } > > ...... > > } > > I think the loop should be terminated once we find a SootClass c s.t. (c.declaresMethod(methodSig)&& ! isVisible( c, m )). > > The reason is as follows: think of a Class A ,which has public method f(), Class B which extends A and has a redefined private method f(), Class C extends B and doesn't redefine method f(). Then the instance of C can't access any f(), either in A() or in B(). But in your code, A.f() will be returned. > > However, the case I mentioned can't appear in normally compiled java code because B can't override f() in A with weaker access privileges. But maybe it will appear in maliciously/purposefully made bytecode. > > As a conclusion, there is no problem in general cases, but there is a mistake semantically, IMHO. > > Regards > > -Weilei > > > > > > > > >
Attachment:
Test.tar.gz
Description: Binary data