java反射访问私有方法的的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java反射访问私有方法的的问题相关的知识,希望对你有一定的参考价值。
LeverageUtil lv =new LeverageUtil();
Class a = lv.getClass();
Method b = a.getDeclaredMethod("isPoXlfICE", new Class[]boolean.class);
b.setAccessible(true);
b.invoke(a.newInstance(),new Object[]null);
这是我写的反射机制访问另一个类的私有方法的代码,代码本身没问题,但在用的时候老是提示The method b is undefined for the type Class,method是private static boolean类型
利用反射还可以访问内部类、匿名内部类的私有属性。
用java自带的java -private 类名 反编译命令可以查看类的完整定义。(参考think in java)
下面举例子说明。首先定义一个接口
Java代码
public interface Ref
public void f();
public interface Ref
public void f();
接口的实现类
Java代码
public class RefImpl implements Ref
//实现接口方法
public void f()
System.out.println("public method f()");
void g(String args)
System.out.println("package method g():" + args);
private void w()
System.out.println("private method w()");
public class RefImpl implements Ref
//实现接口方法
public void f()
System.out.println("public method f()");
void g(String args)
System.out.println("package method g():" + args);
private void w()
System.out.println("private method w()");
测试类
Java代码
public class TestRef
public static void main(String[] args)
Ref ref = new RefImpl();
System.out.println(ref.getClass().getSimpleName()); //RefImpl类型
ref.f(); //调用接口方法
// ref.g(); //向上转型后实现类添加的方法不能调用
if(ref instanceof RefImpl)
RefImpl ref1 = (RefImpl)ref; //类型识别后转型
ref1.g("zhouyang");
// ref1.w(); //私有方法不能访问
//通过反射调用方法
try
Ref ref2 = new RefImpl();
Method m = ref2.getClass().getDeclaredMethod("f");
Method m1 = ref2.getClass().getDeclaredMethod("g", String.class);//有参的方法
Method m2 = ref2.getClass().getDeclaredMethod("w");
System.out.println("==============");
m.invoke(ref); //调用方法f()
m1.invoke(ref, "yangzhou");
m2.setAccessible(true);///调用private方法的关键一句话
m2.invoke(ref);
catch (Exception e)
e.printStackTrace();
//java的javap反编译能够查看类的信息,-private 开关能够打开所有信息
//javap -private 类名 类必须是编译成.calss 文件
//利用反射访问私有成员,改变私有成员值,但是final域可以访问不可改变
PrivateField pf = new PrivateField();
// ps.ss; //私有成员不能访问
//打印原来的成员值
pf.print();
try
//反射访问和改变原来值
Field[] f = pf.getClass().getDeclaredFields();
for(int i=0;i<f.length;i++)
f[i].setAccessible(true);
System.out.println(f[i].getType());//打印字段类型
System.out.println(f[i].get(pf)); //打印值
if("ss".equals(f[i].getName()))
f[i].set(pf, "hehe"); //修改成员值
else
f[i].setInt(pf, 55);
//重新打印修改后的成员值,final域值不变
pf.print();
catch (Exception e)
e.printStackTrace();
/*打印输出的结果
* RefImpl
public method f()
&nb 参考技术A Java反射之访问私有属性或方法
AccessibleObject类是Field、Method、和Constructor对象的基类。它提供了将反射的对象标记为在使用时取消默认Java语言访问控制检查的能力。对于公共成员、默认(打包)访问成员、受保护成员和私有成员,在分别使用Field、Method和Constructor对象来设置或获得字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查。
当反射对象的accessible标志设为true时,则表示反射的对象在使用时应该取消Java语言访问检查。反之则检查。由于JDK的安全检查耗时较多,所以通过setAccessible(true)的方式关闭安全检查来提升反射速度。
举例代码:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 用Java反射机制来调用private方法
* @author pieryon
*
*/
public class Reflect
public static void main(String[] args) throws Exception
//直接创建对象
Person person = new Person();
Class<?> personType = person.getClass();
//访问私有方法
//getDeclaredMethod可以获取到所有方法,而getMethod只能获取public
Method method = personType.getDeclaredMethod("say", String.class);
//抑制Java对访问修饰符的检查
method.setAccessible(true);
//调用方法;person为所在对象
method.invoke(person, "Hello World !");
//访问私有属性
Field field = personType.getDeclaredField("name");
field.setAccessible(true);
//为属性设置值;person为所在对象
field.set(person, "WalkingDog");
System.out.println("The Value Of The Field is : " + person.getName());
//JavaBean
class Person
private String name;
//每个JavaBean都应该实现无参构造方法
public Person()
public String getName()
return name;
private void say(String message)
System.out.println("You want to say : " + message);
参考技术B 静态,用另一个取反射的方法
如
Class c;
Method m = c.getMethod("method name", new Class[] int.class, int.class, int.class,int.class);
m.invoke(c, new Object[] 1,2, 3, 4);追问
为什么会提示b没有定义呢?
追答LeverageUtil lv =new LeverageUtil();
Class a = lv.getClass();
Method b = a.getDeclaredMethod("isPoXlfICE", new Class[]boolean.class);
b.setAccessible(true);
b.invoke(a, new Object[]false); //boolean 不支持null。Boolean则可以
如果a方法有三个参数的话invoke只加一个false可以吗? 多谢了
追答不可以的,一定要对应(个数、类型都相等)。
本回答被提问者采纳如何限制开发人员使用反射访问Java中的私有方法和构造函数?
【中文标题】如何限制开发人员使用反射访问Java中的私有方法和构造函数?【英文标题】:How to restrict developers to use reflection to access private methods and constructors in Java? 【发布时间】:2011-11-25 20:50:00 【问题描述】:如何限制开发者使用反射访问Java中的私有方法和构造函数?
使用普通的 Java 代码,我们无法访问类之外的私有构造函数或私有方法。但是通过使用反射,我们可以访问 Java 类中的任何私有方法和构造函数。
那么我们怎样才能为我们的 Java 代码提供安全性呢?
【问题讨论】:
这对于签名的 jar 来说是一个不错的选择。 “在任何情况下,都不允许对此 jar 文件中的类进行反射”。但我认为,没有这样的功能。 【参考方案1】:使用SecurityManager
和足够严格的security policy 运行您的应用程序。
short summary in the tutorial 有一个the security documentation 和大量信息。
【讨论】:
【参考方案2】:在所有私有方法/构造函数中添加 checkPermission()
方法。
通过断言callerClass=selfClass
使用sun.reflect.Reflection.getCallerClass(int n)
检查权限。
getCallerClass
返回方法 realFramesToSkip
的类在堆栈中向上帧(从零开始),忽略与 java.lang.reflect.Method.invoke()
及其实现相关的帧。第一帧是与此方法关联的帧,因此getCallerClass(0)
返回sun.reflect.Reflection
的Class 对象。
public class PrivateConstructorClass
private PrivateConstructorClass()
checkPerMission();
//you own code go below
void checkPerMission()
Class self = sun.reflect.Reflection.getCallerClass(1);
Class caller = sun.reflect.Reflection.getCallerClass(3);
if (self != caller)
throw new java.lang.IllegalAccessError();
你可以试试reflect,会失败:
public class TestPrivateMain
Object newInstance() throws Exception
final Class<?> c = Class.forName("package.TestPrivate");
final Constructor<?> constructor = c.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
public static void main(String[] args) throws Exception
Object t = new TestPrivateMain().newInstance();
【讨论】:
嗯...但在我看来确实是一个很好的尝试。不稳定的 API 一开始就不应该存在【参考方案3】:您(作为相关代码的开发者)不能这样做。
运行应用程序的最终用户可以安装一个禁止反射的 SecurityManager。
【讨论】:
他当然可以。他在应用程序启动期间安装了安全管理器。 除非他是应用程序的开发者,否则这不是一个选项。我更多地考虑了他“希望限制开发人员 [可能是应用程序的] 使用反射”来反对他希望保持私有的方法的情况。 是什么阻止他在他的类中使用静态初始化程序来安装安全管理器?并且ofc会抛出一个异常,防止class laoding,如果他不能安装呢?以上是关于java反射访问私有方法的的问题的主要内容,如果未能解决你的问题,请参考以下文章
Java-利用反射访问类的私有(private)属性及方法&private的意义
Java-利用反射访问类的私有(private)属性及方法&private的意义