2009-10-11 147 views
7

我有一种情况,用户的代码在反射访问的字段上抛出IllegalAccessException。在访问该字段之前,调用setAccessible(true)。所以,在我看来,这种方法在默默地失败。在什么情况下,Java的field.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; 
} 
+1

打印出异常消息和stacktrace会有帮助。 – NawaMan 2009-10-11 04:03:35

回答

4

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

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

+0

这对我很有意义。谢谢。我不知道这是否是我所看到的问题,但似乎可能,因为我知道已知多个线程位于代码的这一部分。但即使这不是真正的问题,我应该改变我的代码。 – 2009-10-12 05:42:11

0

从Java自身documentationsetAccessible():如果标志是真实的,但

一个SecurityException提出的任何元素的可访问性的输入数组可能不会改变(例如,如果元素对象是Class类的Constructor对象)。如果发生这种SecurityException,则将对象的可访问性设置为标记数组元素直到(并排除)发生异常的元素;超出(并包括)发生异常的元素的元素的可访问性不变。

不幸的是他们不提关于IllegalAccessException.

6

任何它不应该是一个安全管理问题 - 你会得到一个SecurityException或子类。

代码levelField.getInt(*this*)不看的权利...

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

你是否在MessageInfo这个课程中打过电话? (为什么?!?)或MessageInfo的子类? (试图使一个超类行为的私人领域,如果它的受保护?是否MessageInfogetLevel()方法吗?如果是这样,你可以调用super.getLevel()获得的价值,而不是试图这样说的。)

如果不是MessageInfo或子类,这就是你的问题 - 你有MessageInfo类的level字段,你试图从当前类中获取该字段的值。虽然这应该是抛出IllegalArgumentExeception代替IllegalAccessException ...

如果它真的“IllegalAccessExeception” - 试图把一些日志记录if (levelField == null)块内 - 确保它真正被exececuted。该字段是静态的 - 可能有其他实例或方法在其上设置值。

+0

是的,这个类是MessageInfo类的一个子类,它是我正在使用的框架的一部分。所以,level字段是MessageInfo的一个封装保护字段,没有getter,所以它不能被我的子类访问。 此代码适用于许多许多用户,但不是这个特定的代码。所以,我想知道这个特定人员的设置是否可能存在一些特殊情况,使得通话在这里失败。这导致我认为它可能是一个安全管理器的事情,但我想知道是否还有别的东西。 – 2009-10-11 16:52:16

+0

也许这个用户在类路径上有这个框架的更新/旧版本? MessageInfo.level不存在或名称不同?附: - 它是什么框架?可能帮助排除这个... – Nate 2009-10-11 22:43:53

+0

也许,但不太可能。我所描述的框架是Eclipse的JDT。这是我们至少3.3以来一直在使用的代码(在我开始编写项目之前)。我已经测试过Eclipse 3.5.1。如汤姆在接受的答案中所述,我相信这可能是一个线程问题。 – 2009-10-12 05:44:21

相关问题