2009-08-06 11 views
41

Considerate questo esempio:Perché è consentito accedere ai campi privati ​​Java tramite riflessione?

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; 
} 

Sembra illogico che si è permesso di accedere ai campi privati ​​di classi con la riflessione. Perché questa funzionalità è disponibile? Non è "pericoloso" consentire tale accesso?

risposta

55

Private è inteso a prevenire l'uso improprio accidentale, non come un meccanismo di sicurezza. Se si sceglie di ignorarlo, lo si può fare a proprio rischio e l'ipotesi si sa cosa si sta facendo.

+11

+1 per "scopeing, non per sicurezza". – skaffman

+4

+1 perfettamente a destra privato è un suggerimento per gli altri programmatori che non dovrebbero preoccuparsi del membro per mantenere la classe in esecuzione. Ti dà la possibilità di ordinare il tuo codice in alcuni contratti e fare in modo che il compilatore verifichi che non scrivi direttamente o leggi quei membri. Ma se devi rompere il contratto puoi farlo perché un linguaggio di programmazione non deve ostacolare il programmatore, anche se vuole spararsi al ginocchio. – Janusz

+0

quindi, tutto sommato, incapsulamento o dovrei dire: il data hiding riguarda lo scpoing e nulla a che fare con la sicurezza, anche se stai fornendo le tue API come jar di terze parti –

8

La riflessione è pericolosa. Periodo.

Qual è il punto in cui si limita l'utilità di un sistema veramente pericoloso in vista di una sicurezza leggermente aumentata?

Inoltre, la serializzazione automatica richiede la capacità di "succhiare il cervello" da qualsiasi classe; ignorare i modificatori di accesso è una necessità in questo caso.

3

Da: http://java.sun.com/docs/books/tutorial/reflect/

riflessione è comunemente usato dai programmi che richiedono la capacità di esaminare o modificare il comportamento in esecuzione delle applicazioni in esecuzione nella macchina virtuale Java.

È uno strumento che consente di infrangere alcune regole, di lanciarlo sul piede o di usarlo correttamente.

3

Dal pacchetto description of the java.lang.reflect:

classi in questo pacchetto, insieme con java.lang.Class ospitare applicazioni come i debugger, interpreti, ispettori oggetto, classe browser, e servizi come oggetto serializzazione e JavaBeans che necessitano dell'accesso ai membri pubblici di un oggetto di destinazione (in base alla sua classe di esecuzione ) o ai membri dichiarati da una classe data .

Reflection fornisce un meccanismo per accedere alle informazioni sulle classi tramite mezzi che di solito non sono disponibili mediante un'interazione regolare tra classi e oggetti. Uno di questi è consentire l'accesso a campi privati ​​da classi e oggetti esterni.

Sì, la riflessione in generale può effettivamente essere pericolosa, in quanto può esporre l'interno di classi e oggetti.

Tuttavia, è anche uno strumento molto potente che può essere utilizzato per ispezionare l'interno di classi e oggetti, a cui non è possibile accedere con altri mezzi standard.

10

Sì, non è bello ma consente il funzionamento di framework come la serializzazione Java.

Impostazione bandiera accessibile in un oggetto riflesso permessi applicazioni sofisticate con privilegi sufficienti, come Java serializzazione oggetti o di altri meccanismi di persistenza, per manipolare oggetti in modo che sarebbero normalmente vietati.

ho credere che la funzionalità può essere disabilitata attraverso il SecurityManager

http://javabeans.asia/2008/10/12/how_to_set_securitymanager_and_java_security_policy_programmatically.html

21

Sia getDeclaredField() e setAccessible() sono in realtà controllato dal responsabile della sicurezza e un'eccezione quando il codice non è autorizzato a fare Questo. Molto spesso non te ne accorgi, perché il codice Java viene spesso eseguito senza un gestore della sicurezza.

Un'eccezione importante sono le applet, che vengono sempre eseguite con un gestore della sicurezza.

+0

Si dice che "il codice Java viene spesso eseguito senza un responsabile della sicurezza". Non esiste un gestore di sicurezza predefinito? – firstthumb

+1

Woah ... "importante" e "applet" nella stessa frase. Quelli erano i giorni. Lo lascerò come una testimonianza di come i tempi cambiano :-) –

4

Reflection è un'API completa per accedere alle classi. Membri privati ​​e tutti

Nei casi in cui non ti fidi del codice che stai utilizzando (applet e simili) puoi impedire al codice di utilizzare la riflessione. Vedi this Stack Overflow question per i dettagli.

Problemi correlati