我遇到一种情况,用户的代码在通过反射访问的字段上抛出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;
}
最佳答案
已记录setAccessible
引发SecurityException
。请注意,本文档提供了即使不存在SecurityException
也会抛出SecurityManager
的情况。当然,它也可能由于异步异常而失败:Thread.stop
,与NIO缓冲区相关的异常或JVM错误。
这段代码的真正问题(除了使用反射)是存在一个可以设置为部分初始化的字段。这会导致竞争状态(您具有可变的静态,因此您需要担心线程(提示,请避免可变的静态!))。另一个线程可以在调用getInt
之前在同一Field
上调用setAccessible
。正如最初的提问者似乎已经发现的那样,它也不例外。在静态初始化程序中设置字段会更加安全和明确。