[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: maybe a semantic mistake?



Hi,

I'm confused by Feng's example ... if you call public invoke_f() from an instance of C, then isn't it correct for invoke_f() to call the private B.f() because invoke_f() is a method belonging to B and therefore should be able to access all private methods and variables?  I suppose it comes down to interpreting "this": it seems that the VM's (with the exception of Jikes RVM) interpret "this" to be an instance of class B whereas Feng is saying it should be an instance of class C ... I don't think the VM interpretation is necessarily wrong.

Cheers,
Chris

Feng QIAN wrote:
Make Laurie's example more interesting. I add another method in B.java

class B extends A {
  public void f() {  // will be changed to private in jimple
    ...
  }
  public void invoke_f() {
    this.f();
  }
}


In Test.java, I added one extra line to invoke "invoke_f" method on an
instance of C. Guess what, the actual method selected by Sun's JVM
1.4.1_01 (and IBM's) to invoke is B.f().

If read the spec carefully, it says "Let C be the class of objectref ....
If C contains ... and the resolved method is *accessible* from C, ... the
lookup procedure terminates." But in this example, the class of objectref
is C, and B.f is not accessible from C. It should lookup further to A.f().


It might be caused by implication that private method is invoked by
"invokespecial" bytecode only. But no verification error in this case.


The installed version of SableVM 1.0.1 invokes B.f() in both case, it
might not check accessiblity.

JikesRVM throws null pointer exception because the virtual table
entry for f() of class C is interntionally set to null.

Cheers,
-- Feng

On Thu, 6 Mar 2003, Prof. Laurie HENDREN wrote:

  
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