Toepassingsdomeinen
Notitie
Dit artikel is specifiek voor .NET Framework. Dit geldt niet voor nieuwere implementaties van .NET, waaronder .NET 6 en nieuwere versies.
Besturingssystemen en runtime-omgevingen bieden doorgaans een vorm van isolatie tussen toepassingen. Windows gebruikt bijvoorbeeld processen om toepassingen te isoleren. Deze isolatie is nodig om ervoor te zorgen dat code die in de ene toepassing wordt uitgevoerd, geen nadelige gevolgen kan hebben voor andere, niet-gerelateerde toepassingen.
Toepassingsdomeinen bieden een isolatiegrens voor beveiliging, betrouwbaarheid en versiebeheer, en voor het lossen van assembly's. Toepassingsdomeinen worden doorgaans gemaakt door runtimehosts, die verantwoordelijk zijn voor het opstarten van de algemene taalruntime voordat een toepassing wordt uitgevoerd.
De voordelen van het isoleren van toepassingen
In het verleden zijn procesgrenzen gebruikt om toepassingen te isoleren die op dezelfde computer worden uitgevoerd. Elke toepassing wordt in een afzonderlijk proces geladen, waardoor de toepassing wordt geïsoleerd van andere toepassingen die op dezelfde computer worden uitgevoerd.
De toepassingen zijn geïsoleerd omdat geheugenadressen proces-relatief zijn; een geheugenpointer die van het ene proces naar het andere wordt doorgegeven, kan niet op een zinvolle manier worden gebruikt in het doelproces. Daarnaast kunt u geen rechtstreekse aanroepen tussen twee processen maken. In plaats daarvan moet u proxy's gebruiken, die een niveau van indirectie bieden.
Beheerde code moet worden doorgegeven via een verificatieproces voordat deze kan worden uitgevoerd (tenzij de beheerder toestemming heeft verleend om de verificatie over te slaan). Het verificatieproces bepaalt of de code kan proberen toegang te krijgen tot ongeldige geheugenadressen of een andere actie kan uitvoeren die ertoe kan leiden dat het proces waarin deze wordt uitgevoerd, niet goed werkt. Code die de verificatietest doorstaat, wordt gezegd dat deze type-veilig is. Door de mogelijkheid om code als typeveilig te verifiëren, kan de algemene taalruntime een zo groot isolatieniveau bieden als de procesgrens, tegen een veel lagere prestatiekosten.
Toepassingsdomeinen bieden een veiligere en veelzijdigere verwerkingseenheid die de algemene taalruntime kan gebruiken om isolatie tussen toepassingen te bieden. U kunt verschillende toepassingsdomeinen in één proces uitvoeren met hetzelfde isolatieniveau dat in afzonderlijke processen zou bestaan, maar zonder dat u extra overhead hoeft te maken voor het maken van aanroepen tussen processen of het schakelen tussen processen. De mogelijkheid om meerdere toepassingen binnen één proces uit te voeren, verhoogt de schaalbaarheid van de server aanzienlijk.
Het isoleren van toepassingen is ook belangrijk voor toepassingsbeveiliging. U kunt bijvoorbeeld besturingselementen uitvoeren vanuit verschillende webtoepassingen in één browserproces, zodat de besturingselementen geen toegang hebben tot elkaars gegevens en resources.
De isolatie van toepassingsdomeinen heeft de volgende voordelen:
Fouten in de ene toepassing kunnen geen invloed hebben op andere toepassingen. Omdat typeveilige code geen geheugenfouten kan veroorzaken, zorgt het gebruik van toepassingsdomeinen ervoor dat code die in het ene domein wordt uitgevoerd, geen invloed kan hebben op andere toepassingen in het proces.
Afzonderlijke toepassingen kunnen worden gestopt zonder het hele proces te stoppen. Met behulp van toepassingsdomeinen kunt u de code die in één toepassing wordt uitgevoerd, los laden.
Notitie
U kunt afzonderlijke assembly's of typen niet verwijderen. Alleen een volledig domein kan worden uitgepakt.
Code die in de ene toepassing wordt uitgevoerd, heeft geen rechtstreeks toegang tot code of resources van een andere toepassing. De algemene taalruntime dwingt deze isolatie af door directe aanroepen tussen objecten in verschillende toepassingsdomeinen te voorkomen. Objecten die tussen domeinen worden doorgegeven, worden gekopieerd of geopend via proxy. Als het object wordt gekopieerd, is de aanroep naar het object lokaal. Dat wil gezegd: zowel de aanroeper als het object waarnaar wordt verwezen, bevinden zich in hetzelfde toepassingsdomein. Als het object wordt geopend via een proxy, is de aanroep naar het object extern. In dit geval bevinden de aanroeper en het object waarnaar wordt verwezen zich in verschillende toepassingsdomeinen. Aanroepen tussen domeinen gebruiken dezelfde infrastructuur voor externe aanroepen als aanroepen tussen twee processen of tussen twee computers. Daarom moeten de metagegevens voor het object waarnaar wordt verwezen, beschikbaar zijn voor beide toepassingsdomeinen, zodat de methode-aanroep correct kan worden gecompileerd met JIT. Als het aanroepende domein geen toegang heeft tot de metagegevens voor het object dat wordt aangeroepen, kan de compilatie mislukken met uitzondering van het type FileNotFoundException. Zie Externe objecten voor meer informatie. Het mechanisme voor het bepalen hoe objecten kunnen worden geopend tussen domeinen, wordt bepaald door het object. Zie System.MarshalByRefObject voor meer informatie.
Het gedrag van code wordt bepaald door de toepassing waarin deze wordt uitgevoerd. Met andere woorden, het toepassingsdomein biedt configuratie-instellingen zoals beleidsregels voor toepassingsversies, de locatie van eventuele externe assembly's die worden geopend en informatie over waar assembly's moeten worden gevonden die in het domein worden geladen.
Machtigingen die aan code worden verleend, kunnen worden beheerd door het toepassingsdomein waarin de code wordt uitgevoerd.
Toepassingsdomeinen en assembly's
In deze sectie wordt de relatie tussen toepassingsdomeinen en assembly's beschreven. U moet een assembly laden in een toepassingsdomein voordat u de code kunt uitvoeren die deze bevat. Het uitvoeren van een typische toepassing zorgt ervoor dat verschillende assembly's in een toepassingsdomein worden geladen.
De manier waarop een assembly wordt geladen, bepaalt of de JIT-code (Just-In-Time) kan worden gedeeld door meerdere toepassingsdomeinen in het proces en of de assembly kan worden verwijderd uit het proces.
Als een assembly domeinneutraal is geladen, kunnen alle toepassingsdomeinen met dezelfde beveiligingstoekenningenset dezelfde JIT-gecompileerde code delen, waardoor het geheugen dat nodig is voor de toepassing, wordt verminderd. De assembly kan echter nooit uit het proces worden verwijderd.
Als een assembly niet domeinneutraal is geladen, moet deze worden gecompileerd in elk toepassingsdomein waarin deze wordt geladen. De assembly kan echter uit het proces worden verwijderd door alle toepassingsdomeinen waarin deze wordt geladen, te lossen.
De runtimehost bepaalt of assembly's als domeinneutraal moeten worden geladen wanneer de runtime in een proces wordt geladen. Voor beheerde toepassingen past u het LoaderOptimizationAttribute kenmerk toe op de invoerpuntmethode voor het proces en geeft u een waarde op uit de bijbehorende LoaderOptimization opsomming. Voor niet-beheerde toepassingen die als host fungeren voor de algemene taalruntime, geeft u de juiste vlag op wanneer u de methode CorBindToRuntimeEx Function aanroept.
Er zijn drie opties voor het laden van domeinneutrale assembly's:
LoaderOptimization.SingleDomain laadt geen assembly's als domeinneutraal, behalve Mscorlib, die altijd domeinneutraal is geladen. Deze instelling wordt één domein genoemd omdat deze vaak wordt gebruikt wanneer de host slechts één toepassing in het proces uitvoert.
LoaderOptimization.MultiDomain laadt alle assembly's als domeinneutraal. Gebruik deze instelling wanneer er meerdere toepassingsdomeinen in het proces zijn, die allemaal dezelfde code uitvoeren.
LoaderOptimization.MultiDomainHost laadt sterk benoemde assembly's als domeinneutraal, als ze en al hun afhankelijkheden zijn geïnstalleerd in de globale assemblycache. Andere assembly's worden geladen en JIT-gecompileerd voor elk toepassingsdomein waarin ze worden geladen en kunnen dus worden verwijderd uit het proces. Gebruik deze instelling bij het uitvoeren van meer dan één toepassing in hetzelfde proces of als u een combinatie van assembly's hebt die worden gedeeld door veel toepassingsdomeinen en assembly's die moeten worden verwijderd uit het proces.
Gecompileerde JIT-code kan niet worden gedeeld voor assembly's die zijn geladen in de context van de belasting, met behulp van de LoadFrom methode van de Assembly klasse of geladen vanuit afbeeldingen met behulp van overbelastingen van de Load methode die bytematrixen specificeert.
Assembly's die zijn gecompileerd naar systeemeigen code met behulp van de Ngen.exe (Native Image Generator) kunnen worden gedeeld tussen toepassingsdomeinen als ze domeinneutraal zijn geladen wanneer ze voor het eerst in een proces worden geladen.
JIT-gecompileerde code voor de assembly die het invoerpunt van de toepassing bevat, wordt alleen gedeeld als alle afhankelijkheden kunnen worden gedeeld.
Een domeinneutrale assembly kan meerdere keren worden gecompileerd met JIT. Als de beveiligingstoedelingssets van twee toepassingsdomeinen bijvoorbeeld verschillend zijn, kunnen ze niet dezelfde JIT-gecompileerde code delen. Elke kopie van de gecompileerde JIT-assembly kan echter worden gedeeld met andere toepassingsdomeinen met dezelfde toekenningsset.
Wanneer u besluit of u assembly's als domeinneutraal wilt laden, moet u een afweging maken tussen het verminderen van het geheugengebruik en andere prestatiefactoren.
Toegang tot statische gegevens en methoden is langzamer voor domeinneutrale assembly's vanwege de noodzaak om assembly's te isoleren. Elk toepassingsdomein dat toegang heeft tot de assembly, moet een afzonderlijke kopie van de statische gegevens hebben om te voorkomen dat verwijzingen naar objecten in statische velden de grenzen van het domein overschrijden. Als gevolg hiervan bevat de runtime aanvullende logica om een aanroeper naar de juiste kopie van de statische gegevens of methode te leiden. Deze extra logica vertraagt de aanroep.
Alle afhankelijkheden van een assembly moeten worden gevonden en geladen wanneer de assembly domeinneutraal wordt geladen, omdat een afhankelijkheid die niet kan worden geladen domeinneutraal voorkomt dat de assembly domeinneutraal wordt geladen.
Toepassingsdomeinen en threads
Een toepassingsdomein vormt een isolatiegrens voor beveiliging, versiebeheer, betrouwbaarheid en het lossen van beheerde code. Een thread is de besturingssysteemconstructie die wordt gebruikt door de algemene taalruntime om code uit te voeren. Tijdens runtime wordt alle beheerde code in een toepassingsdomein geladen en uitgevoerd door een of meer beheerde threads.
Er is geen een-op-een-correlatie tussen toepassingsdomeinen en threads. Verschillende threads kunnen op elk gewenst moment in één toepassingsdomein worden uitgevoerd en een bepaalde thread is niet beperkt tot één toepassingsdomein. Dat wil gezegd, threads zijn vrij om grenzen van toepassingsdomeinen te overschrijden; er wordt geen nieuwe thread gemaakt voor elk toepassingsdomein.
Op elk gewenst moment wordt elke thread uitgevoerd in een toepassingsdomein. Nul, één of meerdere threads kunnen worden uitgevoerd in een bepaald toepassingsdomein. De runtime houdt bij welke threads worden uitgevoerd in welke toepassingsdomeinen. U kunt het domein zoeken waarin een thread op elk gewenst moment wordt uitgevoerd door de Thread.GetDomain methode aan te roepen.
Toepassingsdomeinen en culturen
Cultuur, die wordt vertegenwoordigd door een CultureInfo object, is gekoppeld aan threads. U kunt de cultuur ophalen die is gekoppeld aan de momenteel uitgevoerde thread met behulp van de CultureInfo.CurrentCulture eigenschap en u kunt de cultuur ophalen of instellen die is gekoppeld aan de momenteel uitgevoerde thread met behulp van de Thread.CurrentCulture eigenschap. Als de cultuur die is gekoppeld aan een thread expliciet is ingesteld met behulp van de Thread.CurrentCulture eigenschap, blijft deze gekoppeld aan die thread wanneer de thread de grenzen van het toepassingsdomein overschrijdt. Anders wordt de cultuur die op elk moment aan de thread is gekoppeld, bepaald door de waarde van de CultureInfo.DefaultThreadCurrentCulture eigenschap in het toepassingsdomein waarin de thread wordt uitgevoerd:
Als de waarde van de eigenschap niet
null
is, wordt de cultuur die door de eigenschap wordt geretourneerd, gekoppeld aan de thread (en daarom geretourneerd door de Thread.CurrentCulture en CultureInfo.CurrentCulture eigenschappen).Als de waarde van de eigenschap is
null
, wordt de huidige systeemcultuur gekoppeld aan de thread.
Programmeren met toepassingsdomeinen
Toepassingsdomeinen worden meestal programmatisch gemaakt en gemanipuleerd door runtimehosts. Soms wil een toepassingsprogramma echter ook werken met toepassingsdomeinen. Een toepassingsprogramma kan bijvoorbeeld een toepassingsonderdeel laden in een domein om het domein (en het onderdeel) te kunnen verwijderen zonder dat de hele toepassing hoeft te worden gestopt.
Dit AppDomain is de programmatische interface voor toepassingsdomeinen. Deze klasse bevat methoden voor het maken en verwijderen van domeinen, het maken van exemplaren van typen in domeinen en het registreren voor verschillende meldingen, zoals het lossen van toepassingsdomeinen. De volgende tabel bevat veelgebruikte AppDomain methoden.
Methode AppDomain | Beschrijving |
---|---|
CreateDomain | Hiermee maakt u een nieuw toepassingsdomein. Het wordt aanbevolen om een overbelasting van deze methode te gebruiken waarmee een AppDomainSetup object wordt opgegeven. Dit is de voorkeursmethode voor het instellen van de eigenschappen van een nieuw domein, zoals de toepassingsbasis of hoofdmap voor de toepassing; de locatie van het configuratiebestand voor het domein; en het zoekpad dat de algemene taalruntime moet gebruiken om assembly's in het domein te laden. |
ExecuteAssembly en ExecuteAssemblyByName | Voert een assembly uit in het toepassingsdomein. Dit is een instantiemethode, zodat deze kan worden gebruikt om code uit te voeren in een ander toepassingsdomein waarnaar u een verwijzing hebt. |
CreateInstanceAndUnwrap | Hiermee maakt u een exemplaar van een opgegeven type in het toepassingsdomein en retourneert u een proxy. Gebruik deze methode om te voorkomen dat de assembly met het gemaakte type in de aanroepende assembly wordt geladen. |
Unload | Voert een correct afsluiten van het domein uit. Het toepassingsdomein wordt pas uitgeladen als alle threads die in het domein worden uitgevoerd, zijn gestopt of zich niet meer in het domein bevinden. |
Notitie
De algemene taalruntime biedt geen ondersteuning voor serialisatie van globale methoden, dus gemachtigden kunnen niet worden gebruikt voor het uitvoeren van globale methoden in andere toepassingsdomeinen.
De niet-beheerde interfaces die worden beschreven in de common language runtime Hosting Interfaces Specification bieden ook toegang tot toepassingsdomeinen. Runtimehosts kunnen interfaces van niet-beheerde code gebruiken om binnen een proces toegang te krijgen tot de toepassingsdomeinen.
De omgevingsvariabele COMPLUS_LoaderOptimization
Een omgevingsvariabele waarmee het standaardoptimalisatiebeleid voor loaders van een uitvoerbare toepassing wordt ingesteld.
Syntaxis
COMPLUS_LoaderOptimization = 1
Opmerkingen
Een typische toepassing laadt verschillende assembly's in een toepassingsdomein voordat de code die ze bevatten, kan worden uitgevoerd.
De manier waarop de assembly wordt geladen, bepaalt of de JIT-code (Just-In-Time) kan worden gedeeld door meerdere toepassingsdomeinen in het proces.
Als een assembly domeinneutraal is geladen, kunnen alle toepassingsdomeinen met dezelfde beveiligingstoekenningsset dezelfde JIT-gecompileerde code delen. Dit vermindert het geheugen dat nodig is voor de toepassing.
Als een assembly niet domeinneutraal is geladen, moet deze worden gecompileerd in elk toepassingsdomein waarin deze wordt geladen en mag het laadprogramma geen interne resources delen tussen toepassingsdomeinen.
Als deze optie is ingesteld op 1, dwingt de COMPLUS_LoaderOptimization omgevingsvlag de runtimehost om alle assembly's op niet-domeinneutrale manier te laden, ook wel SingleDomain genoemd. SingleDomain laadt geen assembly's als domeinneutraal, behalve Mscorlib, dat altijd domeinneutraal is geladen. Deze instelling wordt één domein genoemd omdat deze vaak wordt gebruikt wanneer de host slechts één toepassing in het proces uitvoert.
Let op
De COMPLUS_LoaderOptimization omgevingsvlag is ontworpen voor gebruik in diagnostische en testscenario's. Als de vlag is ingeschakeld, kan dit ernstige vertraging veroorzaken en het geheugengebruik toenemen.
Voorbeeld van code
Als u wilt afdwingen dat alle assembly's niet als domeinneutraal worden geladen voor de IISADMIN-service, kunt u dit doen door toe te voegen aan COMPLUS_LoaderOptimization=1
de waarde voor meerdere tekenreeksen van de omgeving in de HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\IISADMIN-sleutel.
Key = HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\IISADMIN
Name = Environment
Type = REG_MULTI_SZ
Value (to append) = COMPLUS_LoaderOptimization=1