In what situations does Java field.setAccessible (true) fail?

I have a situation where the user code throws an IllegalAccessException in the field that the reflection is accessing. Before accessing the field, setAccessible(true) called. Thus, it seems to me that this method fails silently.

In what situations will this happen? Could this have anything to do with the security manager?

Here is a piece of code that throws an exception:

 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; } 
+7
java reflection
source share
3 answers

setAccessible documented to throw a SecurityException . Please note that in the documentation there are cases when a SecurityException will be thrown, even if there is no SecurityManager . Of course, it can also fail due to an asynchronous exception: Thread.stop , an exception related to the NIO buffer or a JVM error.

The real problem with this code (except that it uses reflection) is that there is a field that can be set to partial initialization. This causes a race condition (you have a variable static, so you need to worry about threads (hint, avoid mutable statics!)). Another thread may call getInt in the same Field before calling setAccessible . And, as it turned out, the initial questionnaire seems to be no exception. It would be much safer and clearer to configure a field in a static initializer.

+4
source share

This should not be a security manager problem - you will get a SecurityException or a subclass.

The code levelField.getInt(*this*) does not look right ...

You must pass an instance of MessageInfo as a parameter.

Are you calling this from the MessageInfo class? (why?!?) or a subclass of MessageInfo ? (Trying to make a private superclass field acts as if it were protected? Does MessageInfo a getLevel() method? If so, you can call super.getLevel() to get the value, rather than trying it that way.)

If it is not MessageInfo or a subclass, your problem is that you have a level field in the MessageInfo class and you are trying to get the value of this field from the current class. Although this should be IllegalArgumentExeception instead of IllegalAccessException ...

If this is truly an "IllegalAccessExeception" - try putting some records inside this if (levelField == null) block - make sure it is really exececuted. The field is static - there may be some other instance or method setting a value on it.

+6
source share

From the native documentation for setAccessible() :

Security occurs if the flag is true, but the accessibility of any of the elements in the input array cannot be changed (for example, if the element object is a Constructor object for the Class class). In the event of such an exclusion of SecurityEx accessibility for objects, a flag is set for the elements of the upto array (and exception) of the element for which the exception occurred; the availability of elements outside (and including) the element for which the exception occurred has not changed.

Unfortunately, they do not say anything about IllegalAccessException.

0
source share

All Articles