反映仅具有包级别访问权限的 class
Reflecting a class with only package level access
我不太确定如何反映只有包级访问权限的 class。我知道如何反映任何具有 public 访问权限的 class,但我不知道如何反映以下示例:
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 {}
如您所见,class one
仅具有包级访问权限。这让我难以反映 class。我继续收到编译器错误,指出:
Main.java:4: error: oneimpl is not public in one; cannot be accessed from outside package
oneimpl o = con.newInstance(t);
我已经查看了一些帖子,自己解决了这个问题,但即使在阅读了大部分 "similar questions"、阅读了 AccessibilityObject
api 并阅读了一般性反思之后我仍然不清楚如何实现这一点。
最终我想做的是反映 API 的特定部分来构建对象,以便 soot/spark 可以构建适当的调用图。我实际上并没有在 android API.
内部工作
您需要在每一步都使用反射才能完成您想要做的事情。
首先,由于您不能从包外部直接引用包 one
中的包范围 class,因此您需要动态加载 class(另请注意使用 ?
而不是直接使用 oneimpl
):
Class<?> oneImplClass = Class.forName("one.oneimpl");
然后你可以获得构造函数和doIt
方法(确保你将这两个都设置为可访问,否则你会得到运行时错误):
Constructor<?> constructor = oneImplClass.getDeclaredConstructor(test.class);
constructor.setAccessible(true);
Method doIt = oneImplClass.getDeclaredMethod("doIt");
doIt.setAccessible (true);
接下来,实例化 class。你必须将它转换为 Object
因为你不能直接引用 class):
Object oneImpl = (Object) constructor.newInstance();
最后,您可以调用 doIt
方法:
doIt.invoke(oneImpl);
最后一点:在命名 class 时,您应该遵循 Java 命名约定:oneimpl
应该是 OneImpl
,test
应该是Test
。否则 one.oneimpl
之类的东西最终看起来像一个包名称而不是完全限定的 class 名称。
public static void main(String[] args) throws Exception {
test t = new test();
Class<?> oneimpl = Main.class.getClassLoader().loadClass("one.oneimpl");
Constructor<?> con = oneimpl.getDeclaredConstructor(test.class);
con.setAccessible(true);
Object o = con.newInstance(t);
Method m = oneimpl.getDeclaredMethod("doIt");
m.setAccessible(true);
m.invoke(o);
}
我不太确定如何反映只有包级访问权限的 class。我知道如何反映任何具有 public 访问权限的 class,但我不知道如何反映以下示例:
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 {}
如您所见,class one
仅具有包级访问权限。这让我难以反映 class。我继续收到编译器错误,指出:
Main.java:4: error: oneimpl is not public in one; cannot be accessed from outside package
oneimpl o = con.newInstance(t);
我已经查看了一些帖子,自己解决了这个问题,但即使在阅读了大部分 "similar questions"、阅读了 AccessibilityObject
api 并阅读了一般性反思之后我仍然不清楚如何实现这一点。
最终我想做的是反映 API 的特定部分来构建对象,以便 soot/spark 可以构建适当的调用图。我实际上并没有在 android API.
内部工作您需要在每一步都使用反射才能完成您想要做的事情。
首先,由于您不能从包外部直接引用包 one
中的包范围 class,因此您需要动态加载 class(另请注意使用 ?
而不是直接使用 oneimpl
):
Class<?> oneImplClass = Class.forName("one.oneimpl");
然后你可以获得构造函数和doIt
方法(确保你将这两个都设置为可访问,否则你会得到运行时错误):
Constructor<?> constructor = oneImplClass.getDeclaredConstructor(test.class);
constructor.setAccessible(true);
Method doIt = oneImplClass.getDeclaredMethod("doIt");
doIt.setAccessible (true);
接下来,实例化 class。你必须将它转换为 Object
因为你不能直接引用 class):
Object oneImpl = (Object) constructor.newInstance();
最后,您可以调用 doIt
方法:
doIt.invoke(oneImpl);
最后一点:在命名 class 时,您应该遵循 Java 命名约定:oneimpl
应该是 OneImpl
,test
应该是Test
。否则 one.oneimpl
之类的东西最终看起来像一个包名称而不是完全限定的 class 名称。
public static void main(String[] args) throws Exception {
test t = new test();
Class<?> oneimpl = Main.class.getClassLoader().loadClass("one.oneimpl");
Constructor<?> con = oneimpl.getDeclaredConstructor(test.class);
con.setAccessible(true);
Object o = con.newInstance(t);
Method m = oneimpl.getDeclaredMethod("doIt");
m.setAccessible(true);
m.invoke(o);
}