Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Annotazioni
Questo articolo è specifico di .NET Framework. Non si applica alle implementazioni più recenti di .NET, incluse .NET 6 e versioni successive.
I sistemi operativi e gli ambienti di runtime offrono in genere una qualche forma di isolamento tra le applicazioni. Ad esempio, Windows usa processi per isolare le applicazioni. Questo isolamento è necessario per garantire che il codice in esecuzione in un'applicazione non possa influire negativamente su altre applicazioni non correlate.
I domini applicazione forniscono un limite di isolamento per sicurezza, affidabilità e controllo delle versioni e per lo scaricamento degli assembly. I domini delle applicazioni vengono in genere creati dagli host di runtime, responsabili dell'inizializzazione del Common Language Runtime prima dell'esecuzione di un'applicazione.
Vantaggi dell'isolamento delle applicazioni
Storicamente, i limiti dei processi sono stati usati per isolare le applicazioni in esecuzione nello stesso computer. Ogni applicazione viene caricata in un processo separato, che isola l'applicazione da altre applicazioni in esecuzione nello stesso computer.
Le applicazioni sono isolate perché gli indirizzi di memoria sono relativi al processo; Un puntatore alla memoria passato da un processo a un altro non può essere usato in modo significativo nel processo di destinazione. Inoltre, non è possibile effettuare chiamate dirette tra due processi. È invece necessario usare i proxy, che forniscono un livello di riferimento indiretto.
Il codice gestito deve essere passato tramite un processo di verifica prima che possa essere eseguito (a meno che l'amministratore non abbia concesso l'autorizzazione per ignorare la verifica). Il processo di verifica determina se il codice può tentare di accedere a indirizzi di memoria non validi o eseguire un'altra azione che potrebbe causare il corretto funzionamento del processo in cui è in esecuzione. Il codice che supera il test di verifica è detto sicuro rispetto ai tipi. La possibilità di verificare il codice come sicuro rispetto ai tipi consente al Common Language Runtime di fornire un livello di isolamento pari al limite del processo, con un costo di prestazioni molto inferiore.
I domini applicazione offrono un'unità di elaborazione più sicura e versatile che Common Language Runtime può usare per garantire l'isolamento tra le applicazioni. È possibile eseguire più domini applicazione in un singolo processo con lo stesso livello di isolamento che esisterebbe in processi separati, ma senza incorrere in un sovraccarico aggiuntivo di effettuare chiamate tra processi o passare da un processo all'altro. La possibilità di eseguire più applicazioni all'interno di un singolo processo aumenta notevolmente la scalabilità del server.
L'isolamento delle applicazioni è anche importante per la sicurezza delle applicazioni. Ad esempio, è possibile eseguire controlli da diverse applicazioni Web in un singolo processo del browser in modo che i controlli non possano accedere tra loro dati e risorse.
L'isolamento fornito dai domini applicazione offre i vantaggi seguenti:
Gli errori in un'applicazione non possono influire su altre applicazioni. Poiché il codice sicuro rispetto ai tipi non può causare errori di memoria, l'uso dei domini di applicazione garantisce che il codice in esecuzione in un dominio non possa influire sulle altre applicazioni all'interno del processo.
È possibile arrestare singole applicazioni senza arrestare l'intero processo. L'uso dei domini applicazione consente di scaricare il codice in esecuzione in una singola applicazione.
Annotazioni
Non è possibile scaricare singoli assembly o tipi. È possibile scaricare solo un dominio completo.
Il codice in esecuzione in un'applicazione non può accedere direttamente al codice o alle risorse da un'altra applicazione. Common Language Runtime applica questo isolamento impedendo chiamate dirette tra oggetti in domini applicazione diversi. Gli oggetti che passano tra domini vengono copiati o acceduti tramite proxy. Se l'oggetto viene copiato, la chiamata all'oggetto è locale. Ovvero, sia il chiamante che l'oggetto a cui si fa riferimento si trovano nello stesso dominio applicazione. Se l'oggetto è accessibile tramite un proxy, la chiamata all'oggetto è remota. In questo caso, il chiamante e l'oggetto a cui si fa riferimento si trovano in domini applicazione diversi. Le chiamate tra domini usano la stessa infrastruttura di chiamata remota delle chiamate tra due processi o tra due computer. Di conseguenza, i metadati per l'oggetto a cui si fa riferimento devono essere disponibili per entrambi i domini applicativi per consentire la corretta compilazione JIT della chiamata al metodo. Se il dominio chiamante non ha accesso ai metadati per l'oggetto chiamato, la compilazione potrebbe non riuscire con un'eccezione di tipo FileNotFoundException. Per altre informazioni, vedere Oggetti remoti. Il meccanismo per determinare come è possibile accedere agli oggetti tra domini è determinato dall'oggetto . Per altre informazioni, vedere System.MarshalByRefObject.
Il comportamento del codice è limitato dall'applicazione in cui viene eseguita. In altre parole, il dominio applicazione fornisce impostazioni di configurazione come i criteri di versione dell'applicazione, il percorso di tutti gli assembly remoti a cui accede e informazioni su dove individuare gli assembly caricati nel dominio.
Le autorizzazioni concesse al codice possono essere controllate dal dominio dell'applicazione in cui è in esecuzione il codice.
Dei domini applicazione e degli assembly
In questa sezione viene descritta la relazione tra domini applicazione e assembly. È necessario caricare un assembly in un dominio applicazione prima di poter eseguire il codice che contiene. L'esecuzione di un'applicazione tipica causa il caricamento di diversi assembly in un dominio dell'applicazione.
Il modo in cui viene caricato un assembly determina se il codice compilato JIT (Just-In-Time) può essere condiviso da più domini applicazione nel processo e se l'assembly può essere scaricato dal processo.
Se un assembly viene caricato indipendente dal dominio, tutti i domini applicazione che condividono lo stesso set di concessioni di sicurezza possono condividere lo stesso codice compilato JIT, riducendo così la memoria richiesta dall'applicazione. Tuttavia, l'assemblaggio non può mai essere discaricato dal processo.
Se un assembly non viene caricato neutro rispetto al dominio, deve essere compilato JIT in ogni dominio applicativo in cui viene caricato. Tuttavia, l'assembly deve essere scaricato dal processo scaricando tutti i domini di applicazione in cui viene caricato.
L'host di runtime determina se caricare gli assembly come indipendente dal dominio quando carica il runtime in un processo. Per le applicazioni gestite, applicare l'attributo LoaderOptimizationAttribute al metodo del punto di ingresso per il processo e specificare un valore dell'enumerazione associata LoaderOptimization . Per le applicazioni non gestite che ospitano Common Language Runtime, specificare il flag appropriato quando si chiama il metodo CorBindToRuntimeEx Function .
Sono disponibili tre opzioni per il caricamento di assembly indipendenti dal dominio:
LoaderOptimization.SingleDomain non carica alcun assembly come neutrale al dominio, ad eccezione di Mscorlib, che viene sempre caricato come neutrale al dominio. Questa impostazione viene chiamata dominio singolo perché viene comunemente usata quando l'host esegue solo una singola applicazione nel processo.
LoaderOptimization.MultiDomain carica tutti gli assembly come neutrali rispetto al dominio. Usare questa impostazione quando sono presenti più domini applicazione nel processo, che eseguono lo stesso codice.
LoaderOptimization.MultiDomainHost carica assembly con nome sicuro come neutro rispetto al dominio, se essi e tutte le loro dipendenze sono state installate nella Global Assembly Cache. Gli altri assembly vengono caricati e compilati JIT separatamente per ogni dominio applicativo in cui vengono caricati e quindi possono essere scaricati dal processo. Usare questa impostazione quando si eseguono più applicazioni nello stesso processo o se si dispone di una combinazione di assembly condivisi da molti domini di applicazione e assembly che devono essere rimossi dal processo.
Il codice compilato tramite JIT non può essere condiviso per gli assembly caricati nel contesto di caricamento load-from, usando il metodo LoadFrom della classe Assembly, o caricati da immagini usando le sovraccariche del metodo Load che specificano array di byte.
Gli assembly compilati in codice nativo usando il Ngen.exe (Generatore di immagini native) possono essere condivisi tra domini applicazione, se vengono caricati indipendente dal dominio la prima volta che vengono caricati in un processo.
Il codice compilato JIT per l'assembly che contiene il punto di ingresso dell'applicazione viene condiviso solo se è possibile condividere tutte le relative dipendenze.
Un assembly neutro rispetto al dominio può essere JIT-compilato più di una volta. Ad esempio, quando gli insiemi di autorizzazioni di sicurezza di due domini applicativi sono diversi, non possono condividere il codice compilato dallo stesso JIT. Tuttavia, ogni copia dell'assembly compilato JIT può essere condivisa con altri domini applicativi con lo stesso insieme di autorizzazioni.
Quando si decide se caricare gli assembly come indipendenti dal dominio, è necessario stabilire un compromesso tra la riduzione dell'uso della memoria e altri fattori di prestazioni.
L'accesso a dati e metodi statici è più lento per gli assembly indipendenti dal dominio a causa della necessità di isolare gli assembly. Ogni dominio applicazione che accede all'assembly deve avere una copia separata dei dati statici per impedire ai riferimenti agli oggetti in campi statici di attraversare i limiti del dominio. Di conseguenza, il runtime contiene logica aggiuntiva per indirizzare un chiamante alla copia appropriata dei dati o del metodo statico. Questa logica aggiuntiva rallenta la chiamata.
Tutte le dipendenze di un assembly devono essere posizionate e caricate quando l'assembly viene caricato indipendente dal dominio, perché una dipendenza che non può essere caricata indipendente dal dominio impedisce il caricamento dell'assembly indipendente dal dominio.
Domini e thread dell'applicazione
Un dominio applicazione costituisce un limite di isolamento per sicurezza, controllo delle versioni, affidabilità e scaricamento del codice gestito. Un thread è il costrutto del sistema operativo usato da Common Language Runtime per eseguire il codice. In fase di esecuzione, tutto il codice gestito viene caricato in un dominio applicazione e viene eseguito da uno o più thread gestiti.
Non esiste una correlazione uno-a-uno tra domini applicazione e thread. Diversi thread possono essere eseguiti in un singolo dominio applicazione in qualsiasi momento e un determinato thread non è limitato a un singolo dominio applicazione. Ovvero, i thread sono liberi di superare i limiti del dominio dell'applicazione; Non viene creato un nuovo thread per ogni dominio applicazione.
In qualsiasi momento, ogni thread viene eseguito in un dominio applicazione. Zero, uno o più thread potrebbero essere in esecuzione in qualsiasi dominio applicazione specificato. Il runtime tiene traccia dei thread in esecuzione nei domini applicazione. È possibile individuare il dominio in cui un thread viene eseguito in qualsiasi momento chiamando il Thread.GetDomain metodo .
Domini delle applicazioni e contesti culturali
La cultura, rappresentata da un oggetto CultureInfo, è associata ai thread. È possibile ottenere le impostazioni cultura associate al thread attualmente in esecuzione usando la CultureInfo.CurrentCulture proprietà ed è possibile ottenere o impostare le impostazioni cultura associate al thread attualmente in esecuzione usando la Thread.CurrentCulture proprietà . Se la cultura associata a un thread è stata impostata in modo esplicito tramite la proprietà Thread.CurrentCulture, continua a essere associata a tale thread quando il thread attraversa i confini del dominio dell'applicazione. In caso contrario, la cultura associata al thread in un determinato momento viene determinata dal valore della CultureInfo.DefaultThreadCurrentCulture proprietà del dominio dell'applicazione in cui viene eseguito il thread.
Se il valore della proprietà
null
non è, le impostazioni cultura restituite dalla proprietà sono associate al thread, e quindi vengono restituite dalle proprietà Thread.CurrentCulture e CultureInfo.CurrentCulture.Se il valore della proprietà è
null
, la cultura di sistema corrente è assegnata al thread.
Programmazione con domini applicazione
I domini applicazione vengono in genere creati e modificati a livello di codice dagli host di runtime. Tuttavia, a volte un programma applicativo potrebbe anche voler usare i domini dell'applicazione. Ad esempio, un programma dell'applicazione potrebbe caricare un componente dell'applicazione in un dominio per poter scaricare il dominio (e il componente) senza dover arrestare l'intera applicazione.
AppDomain è l'interfaccia programmatica per i domini delle applicazioni. Questa classe include metodi per creare e scaricare domini, creare istanze di tipi nei domini e registrarsi per varie notifiche, ad esempio lo scaricamento del dominio applicazione. Nella tabella seguente sono elencati i metodi di uso comune AppDomain .
Metodo AppDomain | Descrizione |
---|---|
CreateDomain | Crea un nuovo dominio applicazione. È consigliabile utilizzare un overload di questo metodo che specifica l'oggetto AppDomainSetup. Questo è il modo preferito per impostare le proprietà di un nuovo dominio, ad esempio la base dell'applicazione o la directory radice per l'applicazione; il percorso del file di configurazione per il dominio; e il percorso di ricerca usato da Common Language Runtime per caricare gli assembly nel dominio. |
ExecuteAssembly e ExecuteAssemblyByName | Esegue un assembly nel dominio dell'applicazione. Si tratta di un metodo di istanza, quindi può essere usato per eseguire il codice in un altro dominio applicazione a cui si dispone di un riferimento. |
CreateInstanceAndUnwrap | Crea un'istanza di un tipo specificato nel dominio applicazione e restituisce un proxy. Utilizzare questo metodo per evitare di caricare l'assembly contenente il tipo creato nell'assembly chiamante. |
Unload | Esegue un arresto normale del dominio. Il dominio dell'applicazione non viene scaricato finché tutti i thread in esecuzione nel dominio non sono stati arrestati o non si trovano più nel dominio. |
Annotazioni
Common Language Runtime non supporta la serializzazione di metodi globali, pertanto i delegati non possono essere usati per eseguire metodi globali in altri domini applicazione.
Le interfacce non gestite descritte nella Common Language Runtime Hosting Interfaces Specification forniscono anche l'accesso ai domini applicativi. Gli host di runtime possono usare interfacce da codice non gestito per creare e ottenere l'accesso ai domini applicazione all'interno di un processo.
Variabile di ambiente COMPLUS_LoaderOptimization
Variabile di ambiente che imposta i criteri di ottimizzazione del caricatore predefiniti di un'applicazione eseguibile.
Sintassi
COMPLUS_LoaderOptimization = 1
Osservazioni:
Un'applicazione tipica carica diversi assembly in un dominio applicazione prima di poter eseguire il codice che contengono.
La modalità di caricamento dell'assembly determina se il codice compilato JIT (Just-In-Time) può essere condiviso da più domini applicativi nel processo.
Se un assembly viene caricato indipendente dal dominio, tutti i domini applicazione che condividono lo stesso set di concessioni di sicurezza possono condividere lo stesso codice compilato JIT. In questo modo si riduce la memoria richiesta dall'applicazione.
Se un assembly non è caricato in modo neutro rispetto al dominio, deve essere compilato JIT in ogni dominio applicativo in cui viene caricato e il caricatore dell'assembly non deve condividere risorse interne tra i domini applicativi.
Se impostato su 1, il flag di ambiente COMPLUS_LoaderOptimization forza l'host di runtime a caricare tutti gli assembly in modo non indipendente dal dominio noto come SingleDomain. SingleDomain non carica assembly come indipendente dal dominio, ad eccezione di Mscorlib, che viene sempre caricato indipendente dal dominio. Questa impostazione viene chiamata dominio singolo perché viene comunemente usata quando l'host esegue solo una singola applicazione nel processo.
Attenzione
Il flag di ambiente COMPLUS_LoaderOptimization è stato progettato per essere usato negli scenari di diagnostica e test. L'attivazione del flag può causare un rallentamento grave e un aumento dell'utilizzo della memoria.
Esempio di codice
Per forzare tutti gli assembly a non essere caricati come neutri rispetto al dominio per il servizio IISADMIN, è possibile aggiungere COMPLUS_LoaderOptimization=1
al valore multistringa dell'ambiente nella chiave HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\IISADMIN.
Key = HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\IISADMIN
Name = Environment
Type = REG_MULTI_SZ
Value (to append) = COMPLUS_LoaderOptimization=1