androidoverridingdalvikandroid-runtimepackage-private

Android method with default (package) visibility called incorrectly with ART


I've a two classes in different packages like this. Base class:

package com.example.artpackageprivate.base;

public class Base {

    protected final Context mContext;

    public Base(final Context context) {
        mContext = context;
    }

    public void foo() {
        boo();
    }

    /*package*/ void boo()
    {
        Toast.makeText(mContext, "Base", Toast.LENGTH_LONG).show();
    }

    public static void redirect(Base object) {
        object.boo();
    }

and child class:

com.example.artpackageprivate.child;

public class Child extends Base {

    public Child(Context context) {
        super(context);
    }

    @Override
    public void foo() {
        boo();
    }

    public /*or whatever*/ void boo()
    {
        Toast.makeText(mContext, "Child", Toast.LENGTH_LONG).show();
    }

I have an object of class Child and I call child.boo() I expect to get "Child" printed. This is really what I usually get. With Dalvik it actually works always. But when I switch to ART I'm getting 2 different outputs.

When the child.boo() is called from "package tree" of Child class I get "Child". The problem is when I call it from a class in package com.example.artpackageprivate.base. The result is "Base" although the object is an instance of class Child.

Here is the Activity class code which is making the calls (Activity contains only 2 buttons):

package com.example.artpackageprivate;

public class MainActivity extends Activity {

    private Base mBase;
    private Child mChild;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mBase = new Base(this);
        mChild = new Child(this);
    }

    public void onChildButtonClick(View view) {
        Base.redirect(mChild);
    }

    public void onBaseButtonClick(View view) {
        mBase.foo();
    }
}

Running this code on Dalvik and on ART (both android Kitkat) I'm getting 2 different results. Pressing BaseButton the result is always "Base". Result of ChildButton is "Child" on Dalvik and "Base" on ART. How is this possible? Is it some kind of bug in ART?


Solution

  • It was a known bug in Dalvik (and it won't be fixed in Dalvik):

    https://code.google.com/p/android/issues/detail?id=60406

    Since Base.boo() is package private : it cannot be overridden in another package. So result with ART is correct ; result with Dalvik is wrong.

    The concept of "package tree" don't exists in java :

    com.company.a
    com.company.a.b
    com.company.b
    

    are just 3 different packages : there is no special relation between com.company.a and com.company.a.b