代码之家  ›  专栏  ›  技术社区  ›  Andrew Eisenberg

在什么情况下Java的field.setAccessible(true)会失败?

  •  8
  • Andrew Eisenberg  · 技术社区  · 16 年前

    我遇到了一种情况,用户的代码正在抛出 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;
    }
    
    3 回复  |  直到 10 年前
        1
  •  4
  •   Tom Hawtin - tackline    16 年前

    这不应该是安全管理器问题——你会得到SecurityException或子类。

    代码 levelField.getInt(*this*) 看起来不太对劲。..

    你应该传递一个实例 MessageInfo 作为参数。

    你是从内部打电话来的吗 留言信息 班级?(为什么?!?)或子类 留言信息 ?(试图使超类的私有字段表现得好像它受到了保护 留言信息 有一个...,有... getLevel() 方法?如果是这样,你可以打电话 super.getLevel() 获取值,而不是以这种方式尝试。)

    如果不是 留言信息 或者子类,这是你的问题——你有 level 领域 留言信息 类,您正试图从当前类中获取该字段的值。虽然这应该是扔一个 IllegalArgumentExeception IllegalAccessException ...

    如果它真的是“IllegalAccessExeception”,试着在里面放一些日志记录 if (levelField == null) block-确保它真的被执行了。该字段是静态的,可能有其他实例或方法在其上设置值。

        2
  •  6
  •   Nate    16 年前

    setAccessible 被记录为投掷 SecurityException 请注意,文档中给出了以下情况 安全异常 即使没有,也会被抛出 SecurityManager 现在。当然,它也可能因异步异常而失败: Thread.stop ,NIO缓冲区相关异常或JVM错误。

    这段代码的真正问题(除了它使用反射)是,有一个字段可以设置为部分初始化。这会导致竞争条件(你有一个可变的静态,因此你需要担心线程(提示,避免可变的静态!)。另一个线程可能会调用 getInt 在相同的…… Field 之前 set可访问 被称为。正如最初的提问者似乎已经发现的那样,它也不是例外安全的。在静态初始化器中设置字段会更安全、更清晰。

        3
  •  0
  •   Cᴏʀʏ bcherry    16 年前

    Java自己的 documentation 为了 setAccessible() :

    如果标志为真,则引发SecurityException,但输入数组中任何元素的可访问性可能不会改变(例如,如果元素对象是类class的构造函数对象)。在发生这种SecurityException的情况下,对象的可访问性被设置为标记数组元素,直到(不包括)发生异常的元素;发生异常的元素之外(包括)的元素的可访问性保持不变。

    不幸的是,他们没有提到任何关于 IllegalAccessException.