2009-10-11 18 views
7

Tengo una situación en la que el código de un usuario arroja un IllegalAccessException en un campo al que se accede por reflexión. Justo antes de acceder al campo, se llama al setAccessible(true). Entonces, me parece que este método está fallando silenciosamente.¿En qué situaciones fallará el campo field.setAccessible (true) de Java?

¿Bajo qué situaciones sucedería esto? ¿Podría esto tener algo que ver con un gerente de seguridad?

Aquí es el fragmento de código que está causando la excepción:

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

Imprima el mensaje de excepción y stacktrace sería útil. – NawaMan

Respuesta

4

setAccessible está documentado para arrojar un SecurityException. Tenga en cuenta que la documentación proporciona casos en los que se lanzará SecurityException incluso si no hay presente el SecurityManager. Por supuesto, también puede fallar debido a una excepción asíncrona: Thread.stop, excepción relacionada con el búfer NIO o un error de JVM.

El problema real con este código (que no sea que utiliza la reflexión) es que hay un campo que se puede configurar para inicializarse parcialmente. Esto causa una condición de carrera (usted tiene una estática mutable, por lo tanto, debe preocuparse por los hilos (sugerencia, ¡evite estáticas mutables!)).Otro hilo puede llamar al getInt en el mismo Field antes de llamar al setAccessible. Y como el que pregunta original parece haberse enterado, tampoco es una excepción segura. Sería mucho más seguro y más claro configurar el campo en un inicializador estático.

+0

Esto tiene mucho sentido para mí. Gracias. No sé si este es el problema que estoy viendo, pero parece posible porque sé que se sabe que varios hilos habitan esa parte del código. Pero incluso si este no es el problema real, debería cambiar mi código. –

0

Desde la propia documentation Java para setAccessible():

Un SecurityException se eleva si la bandera es cierto, pero la accesibilidad de cualquiera de los elementos de la matriz de entrada no se puede cambiar (por ejemplo, si el objeto del elemento es un objeto Constructor para la clase Class). En el caso de tal SecurityException, la accesibilidad de los objetos está configurada para marcar los elementos de la matriz hasta (y excluyendo) el elemento para el cual ocurrió la excepción; la accesibilidad de los elementos más allá (e incluido) del elemento para el cual ocurrió la excepción no cambia.

Desafortunadamente no mencionan nada sobre un IllegalAccessException.

6

No debería ser un problema de controlador de seguridad - se obtendría una SecurityException o subclase.

El código levelField.getInt(*this*) no se ve bien ...

Usted debería pasar una instancia de MessageInfo como parámetro.

¿Está llamando esto dentro de la clase MessageInfo? (¿por qué?!?) o una subclase de MessageInfo? (Tratando de hacer un campo privado de un acto superclase como si estuviera protegida? ¿Se MessageInfo tienen un método getLevel()? Si es así, se podría llamar super.getLevel() para obtener el valor en lugar de tratar de esta manera.)

Si no es MessageInfo o una subclase, ese es su problema: tiene el campo level de la clase MessageInfo y está tratando de obtener el valor de ese campo fuera de la clase actual. Aunque esto se debe tirar una vez de IllegalArgumentExeceptionIllegalAccessException ...

Si es realmente 'IllegalAccessExeception' - trate de poner un poco de registro dentro de ese bloque if (levelField == null) - asegurarse de que realmente está siendo exececuted. El campo es estático: puede haber alguna otra instancia o método que establezca un valor en él.

+0

Sí, esta clase es una subclase de la clase MessageInfo, que es parte de un marco que estoy usando. Por lo tanto, el campo de nivel es un campo protegido de paquetes de MessageInfo sin getter, y por lo tanto no es accesible para mi subclase. Este código funciona correctamente para muchos, muchos usuarios, pero no este en particular. Entonces, me pregunto si podría haber algo peculiar en la configuración de esta persona en particular que hace que la llamada falle aquí. Eso es lo que me lleva a pensar que posiblemente sea una cuestión de gestión de seguridad, pero me pregunto si podría haber algo más. –

+0

¿Tal vez ese usuario tiene una versión más nueva/más antigua de este marco en el classpath? ¿Uno donde MessageInfo.level no existe o tiene un nombre diferente? PD - ¿Qué marco es? Podría ayudar a solucionar este problema ... – Nate

+0

Quizás, pero poco probable. El marco que estoy describiendo es el JDT de Eclipse. Y este es el código que hemos estado usando desde al menos 3.3 (antes de haber estado trabajando en el proyecto). Y lo he probado hasta e incluyendo Eclipse 3.5.1. Tal como lo describe Tom en la respuesta aceptada, creo que podría tratarse de un problema de subprocesamiento. –

Cuestiones relacionadas