Skip to content
Advertisement

Reflecting a class with only package level access

I’m not quite sure how to go about reflecting a class that only has package-level access. I know how to reflect any class that has public access, but I cannot figure out how to reflect the following example:

public class Main {
    public static void main(String[] args) {
        test t = new test();
        Constructor<one.oneimpl> con = one.oneimpl.class.getDeclaredConstructor(test.class);
        oneimpl o = con.newInstance(t);
        o.doIt();
    }
}

======================

package one;
// implementation class for mimicking android api
class oneimpl extends one {
    Test mTest;
    private oneimpl(test t){mTest = t;}
    public void doIt(){System.out.println("Do It!");}
    public void dontDoit(){System.out.println("Don't Do It!");}
}

======================

package one;
// abstract class for mimicking android api
abstract class one {
    public void doIt();
    public void dontDoIt();
}

======================

package one;
// empty class for mimicking android api
public class test {}

As you can see, the class one only has package-level access. This makes reflecting the class difficult for me. I continue to get compiler errors that states:

Main.java:4: error: oneimpl is not public in one; cannot be accessed from outside package
oneimpl o = con.newInstance(t);

I’ve reviewed a few posts, to solve this on my own, but even after reading most of the “similar questions”, reading the AccessibilityObject api, and reading generic reflection procedures it’s still unclear to me how to achieve this.

Ultimately what I am trying to do is to reflect particular portions of the API to build objects so that soot/spark can build a proper call graph. I’m not actually working inside the android API.

Advertisement

Answer

You’ll need to use reflection at every step in order to do what you’re trying to do.

First, since you can’t directly reference a package-scoped class in package one from outside that package you’ll need to load that class dynamically (also note the use of ? instead of directly using oneimpl):

Class<?> oneImplClass = Class.forName("one.oneimpl");

Then you can get the constructor and the doIt method (make sure you set both of these as accessible, otherwise you’ll get runtime errors):

Constructor<?> constructor = oneImplClass.getDeclaredConstructor(test.class);
constructor.setAccessible(true);
Method doIt = oneImplClass.getDeclaredMethod("doIt");
doIt.setAccessible (true);

Next, instantiate the class. You’ll have to cast it to Object since you can’t reference the class directly):

Object oneImpl = (Object) constructor.newInstance();

Lastly you can invoke the doIt method:

doIt.invoke(oneImpl);

As one last note: you should follow Java naming conventions when naming your classes: oneimpl should be OneImpl and test should be Test. Otherwise things like one.oneimpl end up looking like a package name rather than a fully qualified class name.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement