我试图学习反射,我遇到了这个IllegalAccessException.请参阅以下代码:
public class ReflectionTest
{
public static void main(String[] args)
{
Set<String> myStr = new HashSet<String>();
myStr.add("obj1");
Iterator itr = myStr.iterator();
Method mtd = itr.getClass().getMethod("hasNext");
System.out.println(m.invoke(it));
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试运行此程序时,我得到以下内容:
Exception in thread "main" IllegalAccessException
Run Code Online (Sandbox Code Playgroud)
我不明白发生了什么.有任何想法吗?提前致谢.
Piy*_*too 32
您需要禁止Java语言访问检查,以便使用setAccessible(true)反射性地调用另一个类中的私有方法:
Method mtd= itr.getClass().getMethod("hasNext");
if(!mtd.isAccessible()) {
mtd.setAccessible(true);
}
Run Code Online (Sandbox Code Playgroud)
此外,当启用SecurityManager时,我们需要额外的权限来调用setAccessible(true).否则,我们得到:
C:\ReflectionTest>java -Djava.security.manager CallFoo
Exception in thread "main" java.security.AccessControlException: access denied (java.lang.reflect.ReflectPermission suppressAccessChecks)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264)
at java.security.AccessController.checkPermission(AccessController.java:427)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:107)
at CallFoo.main(CallFoo.java:8)
Run Code Online (Sandbox Code Playgroud)
我们只想将此suppressAccessChecks权限授予受信任的代码源,绝对不会向调用堆栈中的所有类授予.所以我们修改CallFoo.java:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
public class CallFoo {
public static void main(String args[]) throws Exception {
doCallFoo();
}
public static void doCallFoo() throws IllegalAccessException, ClassNotFoundException, NoSuchMethodException,
InvocationTargetException, InstantiationException, PrivilegedActionException {
Class fooClass = Class.forName("Foo");
final Foo foo = (Foo) fooClass.newInstance();
final Method helloMethod = fooClass.getDeclaredMethod("hello");
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
if(!helloMethod.isAccessible()) {
helloMethod.setAccessible(true);
}
helloMethod.invoke(foo);
return null;
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
麻烦的代码是这样的:
itr.getClass().getMethod
Run Code Online (Sandbox Code Playgroud)
你可能想hasNext
在Iterator
类.您编写的是HashMap.KeyIterator
类,根据Java语言访问说明符(或至少反射使用的JDK 1.0的粗略解释)不能用于您的代码.
改为使用:
Iterator.class.getMethod
Run Code Online (Sandbox Code Playgroud)
(如果不是出于学习目的,请远离反思.)
很明显,您当前执行的方法无权访问名为 的方法hasNext
,例如,它是private
或protected
。您可以尝试使用以下命令启用对它的访问method.setAccessible(true);
也可能是您在您的文件中定义了一些限制security manager
(如果您使用例如,linux
则可能已默认包含在发行版 java 包中)。
[编辑]事实证明,Tom Hawtin 确定了正确的根本原因。您确实正在操作HashMap.KeyIterator
。尽管解决方案是使用Iterator.class
而不是itr.getClass()
您仍然可以使用 来启用对它的访问setAccessible(true)
。
归档时间: |
|
查看次数: |
36273 次 |
最近记录: |