我的情况是用户的代码在反射访问的字段上抛出IllegalAccessException
。在访问该字段之前,会调用setAccessible(true)
。所以,在我看来,这种方法是默默失败的。
在什么情况下会发生这种情况?这可能与安全经理有关吗?
以下是导致异常的代码段:
private static Field levelField;
public int getLevel() {
try {
if (levelField == null) {
levelField = MessageInfo.class.getDeclaredField("level");
levelField.setAccessible(true);
}
return levelField.getInt(this); // <-- IllegalAccessException thrown here
} catch (Exception e) {
handleException(e);
}
return ICompilationUnit.NO_AST;
}
答案 0 :(得分:6)
它不应该是安全管理器问题 - 您将获得SecurityException或子类。
代码levelField.getInt(*this*)
看起来不正确......
您应该传递MessageInfo
的实例作为参数。
你是在MessageInfo
班级内打电话吗? (为什么?!?)或MessageInfo
的子类? (尝试创建一个超类的私有字段就好像它受到保护一样?MessageInfo
有getLevel()
方法吗?如果有,你可以调用super.getLevel()
来获取值而不是尝试它这样。)
如果它不是MessageInfo
或子类,那就是你的问题 - 你有level
类的MessageInfo
字段,并且你试图从该字段中获取该字段的值现在的课程。虽然这应该是IllegalArgumentExeception
而不是IllegalAccessException
...
如果它确实是'IllegalAccessExeception' - 尝试在if (levelField == null)
块中放入一些日志记录 - 确保它真的被执行了。该字段是静态的 - 可能有一些其他实例或方法在其上设置值。
答案 1 :(得分:4)
setAccessible
以抛出SecurityException
。请注意,文档提供了即使没有SecurityException
也会引发SecurityManager
的情况。当然,它也可能由于异步异常而失败:Thread.stop
,NIO缓冲区相关异常或JVM错误。
此代码的真正问题(除了使用反射之外)是有一个字段可以设置为部分初始化。这会导致竞争条件(你有一个可变的静态,因此你需要担心线程(提示,避免可变静态!))。在调用getInt
之前,另一个主题可能会在Field
上调用setAccessible
。正如原始提问者似乎已经发现的那样,它也不例外。在静态初始化器中设置字段会更安全,更清晰。
答案 2 :(得分:0)
来自Java自己的setAccessible()
IllegalAccessException.
:
如果flag为true,则引发SecurityException,但不能更改输入数组的任何元素的可访问性(例如,如果元素对象是类Class的Constructor对象)。在出现这种SecurityException的情况下,对象的可访问性被设置为对数组元素进行标记,直到(和排除)发生异常的元素;超出(和包括)发生异常的元素的元素的可访问性不变。
不幸的是,他们没有提及{{1}}
的任何内容