我遇到一种情况,用户的代码在通过反射访问的字段上抛出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。正如最初的提问者似乎已经发现的那样,它也不例外。在静态初始化程序中设置字段会更加安全和明确。

08-04 23:41