¿Por qué está permitido acceder a los campos privados de Java a través de la reflexión?
reflection private-members (7)
Considera este ejemplo:
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) {
C c = new C();
try {
Field f = C.class.getDeclaredField("a");
f.setAccessible(true);
Integer i = (Integer)f.get(c);
System.out.println(i);
} catch (Exception e) {}
}
}
class C {
private Integer a =6;
}
Parece ilógico que se le permita acceder a campos privados de clases con reflexión. ¿Por qué está disponible tal funcionalidad? ¿No es "peligroso" permitir ese acceso?
De la descripción del paquete java.lang.reflect
:
Las clases de este paquete, junto con
java.lang.Class
acomodan aplicaciones como depuradores, intérpretes, inspectores de objetos, exploradores de clases y servicios tales como serialización de objetos y JavaBeans que necesitan acceso a los miembros públicos de un objeto de destino (basado en su clase de tiempo de ejecución) o los miembros declarados por una clase determinada.
La reflexión proporciona un mecanismo para acceder a la información sobre las clases a través de medios que generalmente no están disponibles mediante la interacción regular entre clases y objetos. Una de ellas es permitir el acceso a campos privados desde clases y objetos externos.
Sí, la reflexión en general puede ser peligrosa, ya que puede exponer las partes internas de las clases y los objetos.
Sin embargo, también es una herramienta muy poderosa que se puede utilizar para inspeccionar las partes internas de las clases y los objetos, a los que no se puede acceder por otros medios estándar.
De: http://java.sun.com/docs/books/tutorial/reflect/
La reflexión es comúnmente utilizada por programas que requieren la capacidad de examinar o modificar el comportamiento en el tiempo de ejecución de las aplicaciones que se ejecutan en la máquina virtual Java.
Es una herramienta que le permite a uno romper algunas reglas, una puede arrojarla sobre su pie o usarla correctamente.
La reflexión es peligrosa. Período.
¿De qué sirve limitar la utilidad de un sistema realmente peligroso por el bien de una seguridad cada vez mayor?
Además, la serialización automatizada requiere la capacidad de "chupar los cerebros" de cualquier clase; ignorar los modificadores de acceso es una necesidad en este caso.
Privado está destinado a prevenir el uso indebido accidental, no como un mecanismo de seguridad. Si elige eludirlo, puede hacerlo bajo su propio riesgo y suponiendo que sabe lo que está haciendo.
Reflection es una API completa para ingresar a las clases. Miembros privados y todo.
En los casos en que no confíe en el código que está ejecutando (applets y similares), puede evitar que el código use la reflexión. Consulte esta pregunta sobre desbordamiento de pila para obtener más detalles.
Sí, no es agradable, pero sí permite que funcionen frameworks como Java Serialization.
Establecer el indicador accesible en un objeto reflejado permite aplicaciones sofisticadas con privilegios suficientes, como Serialización de objetos Java u otros mecanismos de persistencia, para manipular objetos de una manera que normalmente estaría prohibida.
Creo que la funcionalidad se puede desactivar a través del SecurityManager
Tanto getDeclaredField()
como setAccessible()
son realmente verificados por el administrador de seguridad y lanzarán una excepción cuando su código no pueda hacerlo. La mayoría de las veces no lo notarás, porque el código Java a menudo se ejecuta sin un administrador de seguridad.
Una excepción importante son los applets, que siempre se ejecutan con un administrador de seguridad.