2010-05-09 14 views
8

Ho letto alcune documentazioni su classloader, ma im ancora non è sicuro dove e perché sono necessari. L'API di Android dice:uso corretto del programma di caricamento classi (soprattutto in Android)

Carica classi e risorse da un repository . Uno o più caricatori di classe sono installati in fase di esecuzione. Questi sono consultati ogni volta che il sistema di runtime ha bisogno di una classe specifica che non è ancora disponibili in memoria.

Quindi, se ho capito questo corretto, ci possono essere molte classlaoders che sono responsabili per il caricamento di nuove classi. Ma come il sistema decide quale usare? E in quale situazione dovrebbe uno sviluppatore istanziare un nuovo classloader?

Nel API Android per Intent c'è un metodo

public void setExtrasClassLoader (ClassLoader loader) 

La descrizione dice:

Imposta il ClassLoader che verrà utilizzato quando unmarshalling eventuali Parcelable valori dalle comparse di questo Intent.

Quindi posso definire uno speciale classloader in modo che possa passare l'oggetto con un Intent che non sono definiti nell'attività di ricezione? Un esempio:

Se l'attività A che si trova nel Progetto A (in Eclipse) definisce un oggetto che voglio inviare all'attività B nel Progetto B usando putExtra dell'oggetto Intent. Se l'oggetto che viene inviato attraverso l'intento non è definito (codice sorgente nel progetto B), allora c'è un NoClassDefFoundException. Quindi posso usare il metodo setExtraClassloader per evitare questa eccezione? Se sì, come posso decidere quale oggetto classloader devo passare? E come posso istanziarlo correttamente?

risposta

9

ho letto alcune documentazioni su classloader, ma im ancora non è sicuro dove e perché sono necessari.

In generale, non è necessario toccare il sistema di caricamento classe.

E in quale situazione dovrebbe uno sviluppatore istanziare un nuovo classloader?

Dopo circa un decennio di esperienza nella programmazione Java. :-)

Se l'attività A che si trova nella Progetto A (in Eclipse) definisce un oggetto che voglio inviare a Attività B in Project B utilizzando putExtra dell'oggetto intenti. Se questo oggetto che viene inviato tramite Intent non è definito (codice sorgente nel progetto B), , quindi esiste un valore NoClassDefFoundException . Modo da poter utilizzare il metodo setExtraClassloader a evitano questa eccezione?

No, perché Progetto A e Progetto B non possono condividere codice. Metti la classe che ti serve in entrambi i progetti. Oppure utilizzare un'interfaccia di servizio remota con AIDL anziché Intents e extra. Oppure non utilizzare una classe personalizzata, ma piuttosto trattare l'oggetto come una struttura di dati (ad esempio, utilizzare un semplice HashMap di Strings o qualcosa del genere).

+0

ma se questo non è possibile, qual è lo scopo di questo metodo? – RoflcoptrException

+0

Per fare alcuni trucchi davvero fantasiosi all'interno di un singolo progetto. – CommonsWare

+0

I programmi di caricamento di classi personalizzate di solito creano tutti i problemi che risolvono, quindi non sono un buon punto di partenza quando si cerca di risolvere un problema. Se vuoi davvero essere confuso, prova a capire cosa fa Thread.setContextClassLoader. :-) – fadden

4

I caricatori di classe non sono così difficili da comprendere, almeno nello spazio Java disponibile. (Posso insegnarti il ​​sistema ClassLoader in 90 minuti - lo faccio sempre alle esposizioni No Fluff Just Stuff.) Detto questo, il più delle volte non hai bisogno di creare un ClassLoader personalizzato - se vuoi su futz con bytecode, java.lang.instrument è tuo amico. Se vuoi caricare il codice da un URL, controlla java.net.URLClassLoader. Tra questi due, la necessità di un ClassLoader personalizzato è del tutto nulla.

7

Questa è una risposta tardiva, ma speriamo che aiuti gli altri.

I programmi di caricamento di classe in generale vengono utilizzati per caricare codice Java eseguibile in fase di esecuzione. Un buon esempio di questo sarebbe un plugin che viene scaricato da internet. Puoi prendere i dati binari da un file di classe, caricarlo e chiamare le funzioni al suo interno, se necessario. Ovviamente, è necessario utilizzare un'interfaccia o una classe astratta conosciuta dal programma chiamante in modo che sappia come utilizzare la classe.

Un classloader personalizzato viene utilizzato quando i dati della classe binario non sono accessibili in un tipico maniero. Ad esempio, se si dispone di un dispositivo Bluetooth che contiene un file di classe con codice che implementa un'interfaccia, è necessario scrivere un classloader personalizzato per caricare i dati della classe tramite l'interfaccia Bluetooth.

Un'altra ragione per cui si consiglia di scrivere un classloader personalizzato è se si desidera modificare il modo in cui la classe caricata accede ad altre classi. È possibile limitare le classi interne alle quali la classe caricata ha accesso o persino scrivere le proprie classi, modificando il comportamento di una classe interna. Ad esempio, se la classe caricata utilizza la classe Java.io.File, potrebbe essere necessario forzarla per utilizzare una classe interna per accedere ai file in un modo diverso.

In breve, quando si scrive un classloader personalizzato, si modifica il modo in cui viene caricata una classe, nonché il modo in cui la classe caricata caricherà tutte le altre classi.